HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
simulation_gate_ram.cpp
Go to the documentation of this file.
6 
7 namespace hal
8 {
9  namespace
10  {
11  u32 get_data_word(const std::vector<u64>& data, u32 address, u32 width)
12  {
13  u32 start_pos = address * width;
14  u32 row = start_pos >> 6;
15  u32 start_bit = start_pos & 0x3F;
16 
17  if (row >= data.size() || 64 % width != 0 || width > 32)
18  {
19  log_error("hal_simulator", "cannot read data word of width {} at address {0:x}.", width, address);
20  return 0;
21  }
22 
23  // reads right to left
24  return (u32)((data.at(row) >> start_bit) & ((1 << width) - 1));
25  }
26 
27  void set_data_word(std::vector<u64>& data, u32 in_data, u32 address, u32 width)
28  {
29  u32 start_pos = address * width;
30  u32 row = start_pos >> 6;
31  u32 start_bit = start_pos & 0x3F;
32 
33  if (row >= data.size() || 64 % width != 0 || width > 32)
34  {
35  log_error("hal_simulator", "cannot write data word {0:x} of width {} to address {0:x}.", in_data, width, address);
36  return;
37  }
38 
39  // reads right to left
40  u64 mask = ~((((u64)1 << width) - 1) << start_bit);
41  data.at(row) = (data.at(row) & mask) ^ ((u64)in_data << start_bit);
42  }
43  } // namespace
44 
45  NetlistSimulator::SimulationGateRAM::SimulationGateRAM(const Gate* gate) : SimulationGateSequential(gate)
46  {
47  const GateType* gate_type = gate->get_type();
48  const RAMComponent* ram_component = gate_type->get_component_as<RAMComponent>([](const GateTypeComponent* c) { return RAMComponent::is_class_of(c); });
49  assert(ram_component != nullptr);
50 
51  m_bit_size = ram_component->get_bit_size();
52 
53  for (const GateTypeComponent* component : ram_component->get_components([](const GateTypeComponent* c) { return RAMPortComponent::is_class_of(c); }))
54  {
55  const RAMPortComponent* port_component = component->convert_to<RAMPortComponent>();
56 
57  Port simulation_port;
58  simulation_port.clock_func = port_component->get_clock_function();
59  simulation_port.enable_func = port_component->get_enable_function();
60  simulation_port.is_write = port_component->is_write_port();
61 
62  for (GatePin* pin : gate_type->get_pin_group_by_name(port_component->get_data_group())->get_pins())
63  {
64  simulation_port.data_pins.push_back(pin);
65  }
66 
67  for (GatePin* pin : gate_type->get_pin_group_by_name(port_component->get_address_group())->get_pins())
68  {
69  simulation_port.address_pins.push_back(pin);
70  }
71 
72  // determine clock net
73  for (const std::string& var : simulation_port.clock_func.get_variable_names())
74  {
75  if (const GatePin* pin = gate_type->get_pin_by_name(var); pin != nullptr && pin->get_type() == PinType::clock)
76  {
77  simulation_port.clock_net = gate->get_fan_in_net(pin);
78  }
79  }
80 
81  assert(simulation_port.clock_net != nullptr);
82 
83  m_ports.push_back(simulation_port);
84  }
85  }
86 
87  void NetlistSimulator::SimulationGateRAM::initialize(std::map<const Net*, BooleanFunction::Value>& new_events, bool from_netlist, BooleanFunction::Value value)
88  {
89  GateType* gate_type = m_gate->get_type();
90 
91  const RAMComponent* ram_component = gate_type->get_component_as<RAMComponent>([](const GateTypeComponent* c) { return RAMComponent::is_class_of(c); });
92  if (ram_component == nullptr)
93  {
94  log_error("hal_simulator", "cannot find RAM properties for RAM gate '{}' with ID {} of type '{}'.", m_gate->get_name(), m_gate->get_id(), gate_type->get_name());
95  return;
96  }
97 
98  if (from_netlist)
99  {
100  const InitComponent* init_component = gate_type->get_component_as<InitComponent>([](const GateTypeComponent* c) { return InitComponent::is_class_of(c); });
101  if (init_component == nullptr)
102  {
103  log_error("hal_simulator", "cannot find initialization data for RAM gate '{}' with ID {} of type '{}'.", m_gate->get_name(), m_gate->get_id(), gate_type->get_name());
104  return;
105  }
106 
107  const std::string& category = init_component->get_init_category();
108 
109  for (const std::string& identifier : init_component->get_init_identifiers())
110  {
111  const std::string data = std::get<1>(m_gate->get_data(category, identifier));
112 
113  u32 data_len = data.size();
114  assert(data_len % 16 == 0);
115 
116  for (u32 i = 0; i < data_len; i += 16)
117  {
118  m_data.push_back(strtoull(data.substr(data_len - i - 16, 16).c_str(), nullptr, 16));
119  }
120  }
121 
122  if (ram_component->get_bit_size() != m_data.size() * 64)
123  {
124  log_error("hal_simulator", "initialization data does not fit memory size for RAM gate '{}' with ID {} of type '{}'.", m_gate->get_name(), m_gate->get_id(), gate_type->get_name());
125  m_data.clear();
126  return;
127  }
128  }
129  else
130  {
131  u64 init_val;
132 
133  switch (value)
134  {
135  case BooleanFunction::Value::ONE:
136  init_val = 0xFFFFFFFFFFFFFFFF;
137  break;
138  case BooleanFunction::Value::ZERO:
139  init_val = 0x0;
140  break;
141  case BooleanFunction::Value::X:
142  case BooleanFunction::Value::Z:
143  log_error("hal_simulator", "RAM gate '{}' with ID {} of type {} cannot be initialized with value '{}'.", m_gate->get_name(), m_gate->get_id(), gate_type->get_name(), BooleanFunction::to_string(value));
144  return;
145  }
146 
147  assert(ram_component->get_bit_size() % 64 == 0);
148  u32 num_words = ram_component->get_bit_size() / 64;
149 
150  for (u32 i = 0; i < num_words; i++)
151  {
152  m_data.push_back(init_val);
153  }
154  }
155 
156  // generate initial output events (all zero)
157  for (const Port& port : m_ports)
158  {
159  if (!port.is_write)
160  {
161  u32 data_size = port.data_pins.size();
162  for (u32 j = 0; j < data_size; j++)
163  {
164  const Net* out_net = m_gate->get_fan_out_net(port.data_pins.at(j));
165  new_events[out_net] = BooleanFunction::Value::ZERO;
166  }
167  }
168  }
169  }
170 
171  bool NetlistSimulator::SimulationGateRAM::simulate(const Simulation& simulation, const WaveEvent& event, std::map<std::pair<const Net*, u64>, BooleanFunction::Value>& new_events)
172  {
173  UNUSED(simulation);
174  UNUSED(new_events);
175 
176  // is the event triggering a clock pin? if so, remember the clocked port and process later
177  for (size_t i = 0; i < m_ports.size(); i++)
178  {
179  Port& port = m_ports.at(i);
180  if (event.affected_net == port.clock_net && port.clock_func.evaluate(m_input_values).get() == BooleanFunction::ONE)
181  {
182  if (port.enable_func.evaluate(m_input_values).get() == BooleanFunction::Value::ONE)
183  {
184  if (port.is_write)
185  {
186  m_clocked_write_ports.push_back(i);
187  }
188  else
189  {
190  m_clocked_read_ports.push_back(i);
191  }
192  }
193  }
194  }
195 
196  if (!m_clocked_read_ports.empty() || !m_clocked_write_ports.empty())
197  {
198  return false;
199  }
200 
201  // gate fully handled
202  return true;
203  }
204 
205  void NetlistSimulator::SimulationGateRAM::clock(const u64 current_time, std::map<std::pair<const Net*, u64>, BooleanFunction::Value>& new_events)
206  {
207  // compute delay, currently just a placeholder
208  u64 delay = 0;
209 
210  std::unordered_map<std::string, BooleanFunction> functions = m_gate->get_boolean_functions();
211 
212  for (size_t index : m_clocked_read_ports)
213  {
214  Port port = m_ports.at(index);
215 
216  std::vector<BooleanFunction::Value> address_values;
217  for (const GatePin* pin : port.address_pins)
218  {
219  address_values.push_back(m_input_values.at(pin->get_name()));
220  }
221 
222  u32 address = simulation_utils::values_to_int(address_values);
223  u32 data_size = port.data_pins.size();
224 
225  // read data from internal memory
226  u32 read_data = get_data_word(m_data, address, data_size);
227  std::vector<BooleanFunction::Value> data_values = simulation_utils::int_to_values(read_data, data_size);
228 
229  assert(data_values.size() == data_size);
230 
231  // generate events
232  for (u32 i = 0; i < data_size; i++)
233  {
234  const Net* out_net = m_gate->get_fan_out_net(port.data_pins.at(i));
235  new_events[std::make_pair(out_net, current_time + delay)] = data_values.at(i);
236  }
237  }
238 
239  for (size_t index : m_clocked_write_ports)
240  {
241  Port port = m_ports.at(index);
242  u32 address = simulation_utils::get_int_bus_value(m_input_values, port.address_pins);
243  u32 data_size = port.data_pins.size();
244 
245  // write data to internal memory
246  std::vector<BooleanFunction::Value> data_values = simulation_utils::int_to_values(get_data_word(m_data, address, data_size), data_size);
247 
248  for (u32 i = 0; i < data_size; i++)
249  {
250  const GatePin* pin = port.data_pins.at(i);
251 
252  // do not change memory content of masking function specified and not evaluating to 1
253  if (auto func_it = functions.find(pin->get_name()); func_it != functions.end() && func_it->second.evaluate(m_input_values).get() != BooleanFunction::Value::ONE)
254  {
255  continue;
256  }
257 
258  data_values[i] = m_input_values.at(pin->get_name());
259  }
260  u32 write_data = simulation_utils::values_to_int(data_values);
261  set_data_word(m_data, write_data, address, data_size);
262  }
263 
264  m_clocked_read_ports.clear();
265  m_clocked_write_ports.clear();
266  }
267 } // namespace hal
uint64_t u64
Definition: defines.h:42
uint32_t u32
Definition: defines.h:41
#define UNUSED(expr)
Definition: defines.h:49
#define log_error(channel,...)
Definition: log.h:78
u32 get_int_bus_value(const std::unordered_map< std::string, BooleanFunction::Value > &signal_values, const std::vector< GatePin * > &ordered_pins)
std::vector< BooleanFunction::Value > int_to_values(u32 integer, u32 len)
u32 values_to_int(const std::vector< BooleanFunction::Value > &values)
Definition: defines.h:45
void initialize()
Definition: event_log.cpp:302
std::string identifier