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_start_index(start_index), m_next_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_start_index != other.get_start_index()
80  || 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 (m_ascending)
231  {
232  if (index >= m_start_index && index < m_next_index)
233  {
234  auto it = m_pins.begin();
235  std::advance(it, index - m_start_index);
236  return OK(*it);
237  }
238  }
239  else
240  {
241  if (index <= m_start_index && index > m_next_index)
242  {
243  auto it = m_pins.begin();
244  std::advance(it, m_start_index - index);
245  return OK(*it);
246  }
247  }
248 
249  return ERR("no pin exists at index " + std::to_string(index) + " within pin group '" + m_name + "'");
250  }
251 
258  Result<i32> get_index(const T* pin) const
259  {
260  if (pin == nullptr)
261  {
262  return ERR("'nullptr' provided as pin when trying to retrieve index within pin group '" + m_name + "' with ID " + std::to_string(m_id));
263  }
264 
265  if (pin->m_group.first != this)
266  {
267  return ERR("provided pin '" + pin->get_name() + "' does not belong to pin group '" + m_name + "'");
268  }
269 
270  return OK(pin->m_group.second);
271  }
272 
278  bool is_ascending() const
279  {
280  return m_ascending;
281  }
282 
291  {
292  return m_start_index;
293  }
294 
300  bool is_ordered() const
301  {
302  return m_ordered;
303  }
304 
310  void set_ordered(bool ordered = true)
311  {
312  m_ordered = ordered;
313  }
314 
320  bool empty() const
321  {
322  return m_pins.empty();
323  }
324 
330  size_t size() const
331  {
332  return m_pins.size();
333  }
334 
341  bool assign_pin(T* pin)
342  {
343  if (pin == nullptr)
344  {
345  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);
346  return false;
347  }
348 
349  i32 index = 0;
350  if (m_ascending)
351  {
352  index = m_next_index++;
353  m_pins.push_back(pin);
354  }
355  else
356  {
357  if (m_start_index == m_next_index)
358  {
359  // special case empty pin group
360  index = m_start_index;
361  --m_next_index;
362  }
363  else
364  {
365  index = ++m_start_index;
366  }
367  m_pins.push_front(pin);
368  }
369  pin->m_group = std::make_pair(this, index);
370  return true;
371  }
372 
381  {
382  if (pin == nullptr)
383  {
384  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));
385  }
386 
387  if (pin->m_group.first != this)
388  {
389  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));
390  }
391 
392  if (m_ascending && new_index >= m_start_index && new_index < m_next_index)
393  {
394  i32 old_index = pin->m_group.second;
395  if (old_index == new_index)
396  {
397  return OK({});
398  }
399 
400  i32 direction = (old_index > new_index) ? 1 : -1;
401 
402  // move pin within vector
403  m_pins.erase(std::next(m_pins.begin(), old_index - m_start_index));
404  auto it = std::next(m_pins.begin(), new_index - m_start_index);
405  it = m_pins.insert(it, pin);
406 
407  // update indices; 'it' now points to inserted pin
408  for (i32 i = new_index; i != old_index; i += direction)
409  {
410  std::advance(it, direction);
411  std::get<1>((*it)->m_group) += direction;
412  }
413  std::get<1>(pin->m_group) = new_index;
414  }
415  else if (!m_ascending && new_index <= m_start_index && new_index > m_next_index)
416  {
417  i32 old_index = pin->m_group.second;
418  if (old_index == new_index)
419  {
420  return OK({});
421  }
422 
423  i32 direction = (old_index < new_index) ? 1 : -1;
424 
425  // move pin within vector
426  m_pins.erase(std::next(m_pins.begin(), m_start_index - old_index));
427  auto it = std::next(m_pins.begin(), m_start_index - new_index);
428  it = m_pins.insert(it, pin);
429 
430  // update indices; 'it' now points to inserted pin
431  for (i32 i = new_index; i != old_index; i -= direction)
432  {
433  std::advance(it, direction);
434  std::get<1>((*it)->m_group) -= direction;
435  }
436  std::get<1>(pin->m_group) = new_index;
437  }
438  else
439  {
440  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 start index ("
441  + std::to_string(m_start_index) + ") and end index(" + std::to_string(m_next_index - 1) + ") of pin group '" + m_name + "' with ID " + std::to_string(m_id));
442  }
443 
444  return OK({});
445  }
446 
453  bool remove_pin(T* pin)
454  {
455  if (pin == nullptr)
456  {
457  log_warning("pin_group", "'nullptr' given instead of a pin when trying to remove pin from pin group '{}' with ID {}.", m_name, m_id);
458  return false;
459  }
460 
461  if (pin->m_group.first != this)
462  {
463  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);
464  return false;
465  }
466 
467  i32 index = pin->m_group.second;
468  pin->m_group = std::make_pair(nullptr, 0);
469  if (m_ascending)
470  {
471  auto it = std::next(m_pins.begin(), index - m_start_index);
472  it = m_pins.erase(it);
473  for (; it != m_pins.end(); it++)
474  {
475  std::get<1>((*it)->m_group)--;
476  }
477  m_next_index--;
478  }
479  else
480  {
481  if (m_pins.size() == 1)
482  {
483  m_pins.clear();
484  m_next_index++;
485  }
486  else
487  {
488  auto it = m_pins.begin();
489  for (int i = m_start_index; i > index; i--)
490  {
491  std::get<1>((*(it++))->m_group)--;
492  }
493  m_pins.erase(it);
494  --m_start_index;
495  }
496  }
497 
498  return true;
499  }
500 
507  bool contains_pin(T* pin)
508  {
509  if (pin == nullptr)
510  {
511  return false;
512  }
513 
514  if (pin->m_group.first != this)
515  {
516  return false;
517  }
518 
519  return true;
520  }
521 
522  private:
523  u32 m_id;
524  std::string m_name;
525  PinDirection m_direction;
526  PinType m_type;
527  std::list<T*> m_pins;
528  bool m_ascending;
529  i32 m_start_index;
530  i32 m_next_index;
531  bool m_ordered;
532 
533  PinGroup(const PinGroup&) = delete;
534  PinGroup(PinGroup&&) = delete;
535  PinGroup& operator=(const PinGroup&) = delete;
536  PinGroup& operator=(PinGroup&&) = delete;
537  };
538 } // namespace hal
Result< i32 > get_index(const T *pin) const
Definition: pin_group.h:258
bool assign_pin(T *pin)
Definition: pin_group.h:341
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:380
void set_direction(PinDirection direction)
Definition: pin_group.h:180
bool contains_pin(T *pin)
Definition: pin_group.h:507
bool remove_pin(T *pin)
Definition: pin_group.h:453
i32 get_start_index() const
Definition: pin_group.h:290
u32 get_id() const
Definition: pin_group.h:130
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:330
void set_ordered(bool ordered=true)
Definition: pin_group.h:310
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:278
~PinGroup()=default
PinDirection get_direction() const
Definition: pin_group.h:190
bool is_ordered() const
Definition: pin_group.h:300
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:320
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