HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
simulation_gate_ff.cpp
Go to the documentation of this file.
5 
6 namespace hal
7 {
8  NetlistSimulator::SimulationGateFF::SimulationGateFF(const Gate* gate) : SimulationGateSequential(gate)
9  {
10  const GateType* gate_type = gate->get_type();
11  const FFComponent* ff_component = gate_type->get_component_as<FFComponent>([](const GateTypeComponent* c) { return FFComponent::is_class_of(c); });
12  assert(ff_component != nullptr);
13  m_clock_func = ff_component->get_clock_function();
14  m_next_state_func = ff_component->get_next_state_function();
15  m_preset_func = ff_component->get_async_set_function();
16  m_clear_func = ff_component->get_async_reset_function();
17  for (const GatePin* pin : gate_type->get_pins())
18  {
19  switch (pin->get_type())
20  {
21  case PinType::state:
22  if (const Net* net = gate->get_fan_out_net(pin); net != nullptr)
23  {
24  m_state_output_nets.push_back(gate->get_fan_out_net(pin));
25  }
26  break;
27  case PinType::neg_state:
28  if (const Net* net = gate->get_fan_out_net(pin); net != nullptr)
29  {
30  m_state_inverted_output_nets.push_back(gate->get_fan_out_net(pin));
31  }
32  break;
33  case PinType::clock:
34  m_clock_nets.push_back(gate->get_fan_in_net(pin));
35  break;
36  default:
37  break;
38  }
39  }
40 
41  auto behavior = ff_component->get_async_set_reset_behavior();
42  m_sr_behavior_out = behavior.first;
43  m_sr_behavior_out_inverted = behavior.second;
44  }
45 
46  void NetlistSimulator::SimulationGateFF::initialize(std::map<const Net*, BooleanFunction::Value>& new_events, bool from_netlist, BooleanFunction::Value value = BooleanFunction::Value::X)
47  {
48  GateType* gate_type = m_gate->get_type();
49 
50  BooleanFunction::Value inv_value = simulation_utils::toggle(value);
51 
52  if (from_netlist)
53  {
54  // extract init string
55  const InitComponent* init_component = gate_type->get_component_as<InitComponent>([](const GateTypeComponent* c) { return InitComponent::is_class_of(c); });
56  if (init_component == nullptr)
57  {
58  log_error("hal_simulator", "cannot find initialization data for flip-flop '{}' with ID {} of type '{}'.", m_gate->get_name(), m_gate->get_id(), gate_type->get_name());
59  return;
60  }
61  const std::string& init_str = std::get<1>(m_gate->get_data(init_component->get_init_category(), init_component->get_init_identifiers().front()));
62 
63  if (!init_str.empty())
64  {
65  // parse init string
66  value = BooleanFunction::Value::X;
67  if (init_str == "1")
68  {
69  value = BooleanFunction::Value::ONE;
70  }
71  else if (init_str == "0")
72  {
73  value = BooleanFunction::Value::ZERO;
74  }
75  else
76  {
77  log_error("hal_simulator", "init value of flip-flop '{}' with ID {} of type '{}' is neither '1' or '0'.", m_gate->get_name(), m_gate->get_id(), gate_type->get_name());
78  }
79 
80  inv_value = simulation_utils::toggle(value);
81  }
82  }
83 
84  // generate events
85  for (Endpoint* ep : m_gate->get_fan_out_endpoints())
86  {
87  if (ep->get_pin()->get_type() == PinType::state)
88  {
89  new_events[ep->get_net()] = value;
90  }
91  else if (ep->get_pin()->get_type() == PinType::neg_state)
92  {
93  new_events[ep->get_net()] = inv_value;
94  }
95  }
96  }
97 
98  bool NetlistSimulator::SimulationGateFF::simulate(const Simulation& simulation, const WaveEvent& event, std::map<std::pair<const Net*, u64>, BooleanFunction::Value>& new_events)
99  {
100  // compute delay, currently just a placeholder
101  u64 delay = 0;
102 
103  auto async_set = m_preset_func.evaluate(m_input_values).get();
104  auto async_reset = m_clear_func.evaluate(m_input_values).get();
105 
106  // check whether an asynchronous set or reset ist triggered
107  if (async_set == BooleanFunction::ONE || async_reset == BooleanFunction::ONE)
108  {
109  BooleanFunction::Value result = BooleanFunction::Value::X;
110  BooleanFunction::Value inv_result = BooleanFunction::Value::X;
111 
112  if (async_set == BooleanFunction::ONE && async_reset == BooleanFunction::ONE)
113  {
114  // both signals set? -> evaluate special behavior
115  BooleanFunction::Value old_output = BooleanFunction::Value::X;
116  if (!m_state_output_nets.empty())
117  {
118  const Net* out_net = m_state_output_nets[0];
119  if (auto it = simulation.m_events.find(out_net); it != simulation.m_events.end())
120  {
121  old_output = it->second.back().new_value;
122  }
123  }
124  BooleanFunction::Value old_output_inv = BooleanFunction::Value::X;
125  if (!m_state_inverted_output_nets.empty())
126  {
127  auto out_net = m_state_inverted_output_nets[0];
128  if (auto it = simulation.m_events.find(out_net); it != simulation.m_events.end())
129  {
130  old_output_inv = it->second.back().new_value;
131  }
132  }
133  result = simulation_utils::process_clear_preset_behavior(m_sr_behavior_out, old_output);
134  inv_result = simulation_utils::process_clear_preset_behavior(m_sr_behavior_out_inverted, old_output_inv);
135  }
136  else if (async_set == BooleanFunction::ONE)
137  {
138  // only asynch set is 1
139  result = BooleanFunction::Value::ONE;
140  inv_result = simulation_utils::toggle(result);
141  }
142  else if (async_reset == BooleanFunction::ONE)
143  {
144  // only asynch reset is 1
145  result = BooleanFunction::Value::ZERO;
146  inv_result = simulation_utils::toggle(result);
147  }
148 
149  // generate events
150  for (auto out_net : m_state_output_nets)
151  {
152  new_events[std::make_pair(out_net, event.time + delay)] = result;
153  }
154  for (auto out_net : m_state_inverted_output_nets)
155  {
156  new_events[std::make_pair(out_net, event.time + delay)] = inv_result;
157  }
158 
159  return true;
160  }
161  else if (std::find(m_clock_nets.begin(), m_clock_nets.end(), event.affected_net) != m_clock_nets.end())
162  {
163  // return true if the event was completely handled -> true if the gate is NOT clocked at this point
164  return (m_clock_func.evaluate(m_input_values).get() != BooleanFunction::ONE);
165  }
166 
167  return true;
168  }
169 
170  void NetlistSimulator::SimulationGateFF::clock(const u64 current_time, std::map<std::pair<const Net*, u64>, BooleanFunction::Value>& new_events)
171  {
172  // compute delay, currently just a placeholder
173  u64 delay = 0;
174 
175  // compute output
176  BooleanFunction::Value result = m_next_state_func.evaluate(m_input_values).get();
177  BooleanFunction::Value inv_result = simulation_utils::toggle(result);
178 
179  // generate events
180  for (const Net* out_net : m_state_output_nets)
181  {
182  new_events[std::make_pair(out_net, current_time + delay)] = result;
183  }
184  for (const Net* out_net : m_state_inverted_output_nets)
185  {
186  new_events[std::make_pair(out_net, current_time + delay)] = inv_result;
187  }
188  }
189 } // namespace hal
uint64_t u64
Definition: defines.h:42
#define log_error(channel,...)
Definition: log.h:78
BooleanFunction::Value toggle(BooleanFunction::Value v)
BooleanFunction::Value process_clear_preset_behavior(AsyncSetResetBehavior behavior, BooleanFunction::Value previous_output)
Definition: defines.h:45
void initialize()
Definition: event_log.cpp:302
Net * net