HAL
pin_group.h
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved.
4 // Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved.
5 // Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved.
6 // Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 
26 #pragma once
27 
28 #include "hal_core/defines.h"
31 #include "hal_core/utilities/log.h"
33 
34 #include <list>
35 #include <string>
36 #include <unordered_map>
37 #include <vector>
38 
39 namespace hal
40 {
41  class Module;
42  class GateType;
43 
49  template<class T>
50  class PinGroup
51  {
52  public:
64  PinGroup(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending = true, u32 start_index = 0, bool ordered = false)
65  : m_id(id), m_name(name), m_direction(direction), m_type(type), m_ascending(ascending), m_lowest_index(start_index), m_highest_index(start_index), m_ordered(ordered)
66  {
67  }
68 
69  ~PinGroup() = default;
70 
77  bool operator==(const PinGroup<T>& other) const
78  {
79  if (m_id != other.get_id() || m_name != other.get_name() || m_direction != other.get_direction() || m_type != other.get_type() || m_lowest_index != other.get_lowest_index()
80  || m_highest_index != other.get_highest_index() || m_ascending != other.is_ascending() || m_ordered != other.is_ordered())
81  {
82  return false;
83  }
84 
85  std::vector<T*> other_pins = other.get_pins();
86  if (m_pins.size() != other_pins.size())
87  {
88  return false;
89  }
90 
91  auto this_it = m_pins.begin();
92  auto other_it = other_pins.begin();
93  while (this_it != m_pins.end() && other_it != other_pins.end())
94  {
95  if (**this_it++ != **other_it++)
96  {
97  return false;
98  }
99  }
100 
101  return true;
102  }
103 
110  bool operator!=(const PinGroup<T>& other) const
111  {
112  return !operator==(other);
113  }
114 
120  ssize_t get_hash() const
121  {
122  return (uintptr_t)this;
123  }
124 
130  u32 get_id() const
131  {
132  return m_id;
133  }
134 
140  void set_name(const std::string& name)
141  {
142  m_name = name;
143  }
144 
150  const std::string& get_name() const
151  {
152  return m_name;
153  }
154 
161  {
162  m_type = type;
163  }
164 
171  {
172  return m_type;
173  }
174 
181  {
182  m_direction = direction;
183  }
184 
191  {
192  return m_direction;
193  }
194 
202  std::vector<T*> get_pins(const std::function<bool(T*)>& filter = nullptr) const
203  {
204  if (!filter)
205  {
206  return std::vector<T*>(m_pins.begin(), m_pins.end());
207  }
208  else
209  {
210  std::vector<T*> res;
211  for (T* pin : m_pins)
212  {
213  if (filter(pin))
214  {
215  res.push_back(pin);
216  }
217  }
218  return res;
219  }
220  }
221 
229  {
230  if (index >= m_lowest_index && index <= m_highest_index)
231  {
232  auto it = m_pins.begin();
233  if (m_ascending)
234  {
235  std::advance(it, index - m_lowest_index);
236  }
237  else
238  {
239  std::advance(it, m_highest_index - index);
240  }
241  return OK(*it);
242  }
243 
244  return ERR("no pin exists at index " + std::to_string(index) + " within pin group '" + m_name + "'");
245  }
246 
253  Result<i32> get_index(const T* pin) const
254  {
255  if (pin == nullptr)
256  {
257  return ERR("'nullptr' provided as pin when trying to retrieve index within pin group '" + m_name + "' with ID " + std::to_string(m_id));
258  }
259 
260  if (pin->m_group.first != this)
261  {
262  return ERR("provided pin '" + pin->get_name() + "' does not belong to pin group '" + m_name + "'");
263  }
264 
265  return OK(pin->m_group.second);
266  }
267 
273  bool is_ascending() const
274  {
275  return m_ascending;
276  }
277 
283  bool is_descending() const
284  {
285  return !m_ascending;
286  }
287 
294  {
295  return m_lowest_index;
296  }
297 
304  {
305  return m_highest_index;
306  }
307 
316  {
317  return m_ascending ? m_lowest_index : m_highest_index;
318  }
319 
325  bool is_ordered() const
326  {
327  return m_ordered;
328  }
329 
335  void set_ordered(bool ordered = true)
336  {
337  m_ordered = ordered;
338  }
339 
345  bool empty() const
346  {
347  return m_pins.empty();
348  }
349 
355  size_t size() const
356  {
357  return m_pins.size();
358  }
359 
370  bool assign_pin(T* pin)
371  {
372  if (pin == nullptr)
373  {
374  log_warning("pin_group", "'nullptr' given instead of a pin when trying to assign a pin to pin group '{}' with ID {}", m_name, m_id);
375  return false;
376  }
377 
378  i32 index = m_pins.empty() ? m_highest_index : ++m_highest_index;
379 
380  if (m_ascending)
381  {
382  m_pins.push_back(pin);
383  }
384  else
385  {
386  m_pins.push_front(pin);
387  }
388  pin->m_group = std::make_pair(this, index);
389  return true;
390  }
391 
401  {
402  if (pin == nullptr)
403  {
404  return ERR("'nullptr' given instead of a pin when trying to move pin within pin group '" + m_name + "' with ID " + std::to_string(m_id));
405  }
406 
407  if (pin->m_group.first != this)
408  {
409  return ERR("pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " does not belong to pin group '" + m_name + "' with ID " + std::to_string(m_id));
410  }
411 
412  if (new_index >= m_lowest_index && new_index <= m_highest_index)
413  {
414  if (m_ascending)
415  {
416  i32 old_index = pin->m_group.second;
417  if (old_index == new_index)
418  {
419  return OK({});
420  }
421 
422  i32 direction = (old_index > new_index) ? 1 : -1;
423 
424  // move pin within vector
425  m_pins.erase(std::next(m_pins.begin(), old_index - m_lowest_index));
426  auto it = std::next(m_pins.begin(), new_index - m_lowest_index);
427  it = m_pins.insert(it, pin);
428 
429  // update indices; 'it' now points to inserted pin
430  for (i32 i = new_index; i != old_index; i += direction)
431  {
432  std::advance(it, direction);
433  std::get<1>((*it)->m_group) += direction;
434  }
435  std::get<1>(pin->m_group) = new_index;
436  }
437  else
438  {
439  i32 old_index = pin->m_group.second;
440  if (old_index == new_index)
441  {
442  return OK({});
443  }
444 
445  i32 direction = (old_index < new_index) ? 1 : -1;
446 
447  // move pin within vector
448  m_pins.erase(std::next(m_pins.begin(), m_highest_index - old_index));
449  auto it = std::next(m_pins.begin(), m_highest_index - new_index);
450  it = m_pins.insert(it, pin);
451 
452  // update indices; 'it' now points to inserted pin
453  for (i32 i = new_index; i != old_index; i -= direction)
454  {
455  std::advance(it, direction);
456  std::get<1>((*it)->m_group) -= direction;
457  }
458  std::get<1>(pin->m_group) = new_index;
459  }
460  }
461  else
462  {
463  return ERR("new index (" + std::to_string(new_index) + ") for pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " is not between lowest index ("
464  + std::to_string(m_lowest_index) + ") and highest index (" + std::to_string(m_highest_index - 1) + ") of pin group '" + m_name + "' with ID " + std::to_string(m_id));
465  }
466 
467  return OK({});
468  }
469 
478  bool remove_pin(T* pin)
479  {
480  if (pin == nullptr)
481  {
482  log_warning("pin_group", "'nullptr' given instead of a pin when trying to remove pin from pin group '{}' with ID {}.", m_name, m_id);
483  return false;
484  }
485 
486  if (pin->m_group.first != this)
487  {
488  log_warning("pin_group", "pin '{}' with ID {} does not belong to pin group '{}' with ID {}.", pin->get_name(), pin->get_id(), m_name, m_id);
489  return false;
490  }
491 
492  i32 index = pin->m_group.second;
493  pin->m_group = std::make_pair(nullptr, 0);
494 
495  // iterate until at pin to be removed, reduce all indices by 1 on the way
496  // start at highest indices (rbegin() for ascending and begin() for descending)
497  if (m_ascending)
498  {
499  auto it = std::next(m_pins.begin(), index - m_lowest_index);
500  it = m_pins.erase(it);
501  for (; it != m_pins.end(); it++)
502  {
503  std::get<1>((*it)->m_group)--;
504  }
505  }
506  else
507  {
508  auto it = m_pins.begin();
509  for (int i = m_highest_index; i > index; i--)
510  {
511  std::get<1>((*(it++))->m_group)--;
512  }
513  m_pins.erase(it);
514  }
515 
516  m_highest_index = m_pins.empty() ? m_lowest_index : --m_highest_index;
517 
518  return true;
519  }
520 
527  bool contains_pin(T* pin)
528  {
529  if (pin == nullptr)
530  {
531  return false;
532  }
533 
534  if (pin->m_group.first != this)
535  {
536  return false;
537  }
538 
539  return true;
540  }
541 
542  private:
543  u32 m_id;
544  std::string m_name;
545  PinDirection m_direction;
546  PinType m_type;
547  std::list<T*> m_pins;
548  bool m_ascending;
549  i32 m_lowest_index;
550  i32 m_highest_index;
551  bool m_ordered;
552 
553  PinGroup(const PinGroup&) = delete;
554  PinGroup(PinGroup&&) = delete;
555  PinGroup& operator=(const PinGroup&) = delete;
556  PinGroup& operator=(PinGroup&&) = delete;
557  };
558 } // namespace hal
Result< i32 > get_index(const T *pin) const
Definition: pin_group.h:253
bool assign_pin(T *pin)
Definition: pin_group.h:370
std::vector< T * > get_pins(const std::function< bool(T *)> &filter=nullptr) const
Definition: pin_group.h:202
Result< std::monostate > move_pin(T *pin, i32 new_index)
Definition: pin_group.h:400
void set_direction(PinDirection direction)
Definition: pin_group.h:180
bool contains_pin(T *pin)
Definition: pin_group.h:527
i32 get_highest_index() const
Definition: pin_group.h:303
bool remove_pin(T *pin)
Definition: pin_group.h:478
i32 get_start_index() const
Definition: pin_group.h:315
u32 get_id() const
Definition: pin_group.h:130
i32 get_lowest_index() const
Definition: pin_group.h:293
bool operator==(const PinGroup< T > &other) const
Definition: pin_group.h:77
const std::string & get_name() const
Definition: pin_group.h:150
size_t size() const
Definition: pin_group.h:355
void set_ordered(bool ordered=true)
Definition: pin_group.h:335
void set_name(const std::string &name)
Definition: pin_group.h:140
Result< T * > get_pin_at_index(i32 index) const
Definition: pin_group.h:228
bool is_ascending() const
Definition: pin_group.h:273
~PinGroup()=default
PinDirection get_direction() const
Definition: pin_group.h:190
bool is_descending() const
Definition: pin_group.h:283
bool is_ordered() const
Definition: pin_group.h:325
PinGroup(const u32 id, const std::string &name, PinDirection direction, PinType type, bool ascending=true, u32 start_index=0, bool ordered=false)
Definition: pin_group.h:64
void set_type(PinType type)
Definition: pin_group.h:160
ssize_t get_hash() const
Definition: pin_group.h:120
bool empty() const
Definition: pin_group.h:345
PinType get_type() const
Definition: pin_group.h:170
bool operator!=(const PinGroup< T > &other) const
Definition: pin_group.h:110
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
PinDirection
Definition: pin_direction.h:36
PinType
Definition: pin_type.h:36
quint32 u32
PinType type
bool ordered
u32 start_index
bool ascending
PinDirection direction
std::string name
i32 id