HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
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 
52  template<class T>
53  class PinGroup
54  {
55  public:
67  PinGroup(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending = true, u32 start_index = 0, bool ordered = false)
68  : 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)
69  {
70  }
71 
72  ~PinGroup() = default;
73 
80  bool operator==(const PinGroup<T>& other) const
81  {
82  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()
83  || m_highest_index != other.get_highest_index() || m_ascending != other.is_ascending() || m_ordered != other.is_ordered())
84  {
85  return false;
86  }
87 
88  std::vector<T*> other_pins = other.get_pins();
89  if (m_pins.size() != other_pins.size())
90  {
91  return false;
92  }
93 
94  auto this_it = m_pins.begin();
95  auto other_it = other_pins.begin();
96  while (this_it != m_pins.end() && other_it != other_pins.end())
97  {
98  if (**this_it++ != **other_it++)
99  {
100  return false;
101  }
102  }
103 
104  return true;
105  }
106 
113  bool operator!=(const PinGroup<T>& other) const
114  {
115  return !operator==(other);
116  }
117 
123  ssize_t get_hash() const
124  {
125  return (uintptr_t)this;
126  }
127 
133  u32 get_id() const
134  {
135  return m_id;
136  }
137 
143  void set_name(const std::string& name)
144  {
145  m_name = name;
146  }
147 
153  const std::string& get_name() const
154  {
155  return m_name;
156  }
157 
164  {
165  m_type = type;
166  }
167 
174  {
175  return m_type;
176  }
177 
184  {
185  m_direction = direction;
186  }
187 
194  {
195  return m_direction;
196  }
197 
205  std::vector<T*> get_pins(const std::function<bool(T*)>& filter = nullptr) const
206  {
207  if (!filter)
208  {
209  return std::vector<T*>(m_pins.begin(), m_pins.end());
210  }
211  else
212  {
213  std::vector<T*> res;
214  for (T* pin : m_pins)
215  {
216  if (filter(pin))
217  {
218  res.push_back(pin);
219  }
220  }
221  return res;
222  }
223  }
224 
232  {
233  if (index >= m_lowest_index && index <= m_highest_index)
234  {
235  auto it = m_pins.begin();
236  if (m_ascending)
237  {
238  std::advance(it, index - m_lowest_index);
239  }
240  else
241  {
242  std::advance(it, m_highest_index - index);
243  }
244  return OK(*it);
245  }
246 
247  return ERR("no pin exists at index " + std::to_string(index) + " within pin group '" + m_name + "'");
248  }
249 
256  Result<i32> get_index(const T* pin) const
257  {
258  if (pin == nullptr)
259  {
260  return ERR("'nullptr' provided as pin when trying to retrieve index within pin group '" + m_name + "' with ID " + std::to_string(m_id));
261  }
262 
263  if (pin->m_group.first != this)
264  {
265  return ERR("provided pin '" + pin->get_name() + "' does not belong to pin group '" + m_name + "'");
266  }
267 
268  return OK(pin->m_group.second);
269  }
270 
276  bool is_ascending() const
277  {
278  return m_ascending;
279  }
280 
286  bool is_descending() const
287  {
288  return !m_ascending;
289  }
290 
297  {
298  return m_lowest_index;
299  }
300 
307  {
308  return m_highest_index;
309  }
310 
319  {
320  return m_ascending ? m_lowest_index : m_highest_index;
321  }
322 
328  bool is_ordered() const
329  {
330  return m_ordered;
331  }
332 
338  void set_ordered(bool ordered = true)
339  {
340  m_ordered = ordered;
341  }
342 
348  bool empty() const
349  {
350  return m_pins.empty();
351  }
352 
358  size_t size() const
359  {
360  return m_pins.size();
361  }
362 
373  bool assign_pin(T* pin)
374  {
375  if (pin == nullptr)
376  {
377  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);
378  return false;
379  }
380 
381  i32 index = m_pins.empty() ? m_highest_index : ++m_highest_index;
382 
383  if (m_ascending)
384  {
385  m_pins.push_back(pin);
386  }
387  else
388  {
389  m_pins.push_front(pin);
390  }
391  pin->m_group = std::make_pair(this, index);
392  return true;
393  }
394 
404  {
405  if (pin == nullptr)
406  {
407  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));
408  }
409 
410  if (pin->m_group.first != this)
411  {
412  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));
413  }
414 
415  if (new_index >= m_lowest_index && new_index <= m_highest_index)
416  {
417  if (m_ascending)
418  {
419  i32 old_index = pin->m_group.second;
420  if (old_index == new_index)
421  {
422  return OK({});
423  }
424 
425  i32 direction = (old_index > new_index) ? 1 : -1;
426 
427  // move pin within vector
428  m_pins.erase(std::next(m_pins.begin(), old_index - m_lowest_index));
429  auto it = std::next(m_pins.begin(), new_index - m_lowest_index);
430  it = m_pins.insert(it, pin);
431 
432  // update indices; 'it' now points to inserted pin
433  for (i32 i = new_index; i != old_index; i += direction)
434  {
435  std::advance(it, direction);
436  std::get<1>((*it)->m_group) += direction;
437  }
438  std::get<1>(pin->m_group) = new_index;
439  }
440  else
441  {
442  i32 old_index = pin->m_group.second;
443  if (old_index == new_index)
444  {
445  return OK({});
446  }
447 
448  i32 direction = (old_index < new_index) ? 1 : -1;
449 
450  // move pin within vector
451  m_pins.erase(std::next(m_pins.begin(), m_highest_index - old_index));
452  auto it = std::next(m_pins.begin(), m_highest_index - new_index);
453  it = m_pins.insert(it, pin);
454 
455  // update indices; 'it' now points to inserted pin
456  for (i32 i = new_index; i != old_index; i -= direction)
457  {
458  std::advance(it, direction);
459  std::get<1>((*it)->m_group) -= direction;
460  }
461  std::get<1>(pin->m_group) = new_index;
462  }
463  }
464  else
465  {
466  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 ("
467  + 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));
468  }
469 
470  return OK({});
471  }
472 
481  bool remove_pin(T* pin)
482  {
483  if (pin == nullptr)
484  {
485  log_warning("pin_group", "'nullptr' given instead of a pin when trying to remove pin from pin group '{}' with ID {}.", m_name, m_id);
486  return false;
487  }
488 
489  if (pin->m_group.first != this)
490  {
491  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);
492  return false;
493  }
494 
495  i32 index = pin->m_group.second;
496  pin->m_group = std::make_pair(nullptr, 0);
497 
498  // iterate until at pin to be removed, reduce all indices by 1 on the way
499  // start at highest indices (rbegin() for ascending and begin() for descending)
500  if (m_ascending)
501  {
502  auto it = std::next(m_pins.begin(), index - m_lowest_index);
503  it = m_pins.erase(it);
504  for (; it != m_pins.end(); it++)
505  {
506  std::get<1>((*it)->m_group)--;
507  }
508  }
509  else
510  {
511  auto it = m_pins.begin();
512  for (int i = m_highest_index; i > index; i--)
513  {
514  std::get<1>((*(it++))->m_group)--;
515  }
516  m_pins.erase(it);
517  }
518 
519  m_highest_index = m_pins.empty() ? m_lowest_index : --m_highest_index;
520 
521  return true;
522  }
523 
530  bool contains_pin(T* pin)
531  {
532  if (pin == nullptr)
533  {
534  return false;
535  }
536 
537  if (pin->m_group.first != this)
538  {
539  return false;
540  }
541 
542  return true;
543  }
544 
545  private:
546  u32 m_id;
547  std::string m_name;
548  PinDirection m_direction;
549  PinType m_type;
550  std::list<T*> m_pins;
551  bool m_ascending;
552  i32 m_lowest_index;
553  i32 m_highest_index;
554  bool m_ordered;
555 
556  PinGroup(const PinGroup&) = delete;
557  PinGroup(PinGroup&&) = delete;
558  PinGroup& operator=(const PinGroup&) = delete;
559  PinGroup& operator=(PinGroup&&) = delete;
560  };
561 } // namespace hal
Result< i32 > get_index(const T *pin) const
Definition: pin_group.h:256
bool assign_pin(T *pin)
Definition: pin_group.h:373
std::vector< T * > get_pins(const std::function< bool(T *)> &filter=nullptr) const
Definition: pin_group.h:205
Result< std::monostate > move_pin(T *pin, i32 new_index)
Definition: pin_group.h:403
void set_direction(PinDirection direction)
Definition: pin_group.h:183
bool contains_pin(T *pin)
Definition: pin_group.h:530
i32 get_highest_index() const
Definition: pin_group.h:306
bool remove_pin(T *pin)
Definition: pin_group.h:481
i32 get_start_index() const
Definition: pin_group.h:318
u32 get_id() const
Definition: pin_group.h:133
i32 get_lowest_index() const
Definition: pin_group.h:296
bool operator==(const PinGroup< T > &other) const
Definition: pin_group.h:80
const std::string & get_name() const
Definition: pin_group.h:153
size_t size() const
Definition: pin_group.h:358
void set_ordered(bool ordered=true)
Definition: pin_group.h:338
void set_name(const std::string &name)
Definition: pin_group.h:143
Result< T * > get_pin_at_index(i32 index) const
Definition: pin_group.h:231
bool is_ascending() const
Definition: pin_group.h:276
~PinGroup()=default
PinDirection get_direction() const
Definition: pin_group.h:193
bool is_descending() const
Definition: pin_group.h:286
bool is_ordered() const
Definition: pin_group.h:328
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:67
void set_type(PinType type)
Definition: pin_group.h:163
ssize_t get_hash() const
Definition: pin_group.h:123
bool empty() const
Definition: pin_group.h:348
PinType get_type() const
Definition: pin_group.h:173
bool operator!=(const PinGroup< T > &other) const
Definition: pin_group.h:113
uint32_t u32
Definition: defines.h:41
int32_t i32
Definition: defines.h:36
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
Definition: defines.h:45
PinDirection
Definition: pin_direction.h:36
PinType
Definition: pin_type.h:36
PinType type
bool ordered
u32 start_index
bool ascending
PinDirection direction
std::string name
i32 id