16 #include <unordered_map>
20 #define measure_block_time(X)
22 NetlistSimulator::NetlistSimulator(
const std::string& nam) : SimulationEngineEventDriven(nam)
31 log_error(
"hal_simulator",
"net is a nullptr.");
35 if (
auto it = m_simulation.m_events.find(
net); it != m_simulation.m_events.end())
37 if (value == it->second.back().new_value)
45 e.
time = m_current_time;
47 m_event_queue.push_back(e);
50 void NetlistSimulator::initialize_sequential_gates(
const std::function<
bool(
const Gate*)>& filter)
52 if (!m_is_initialized)
54 m_init_seq_gates.push_back(std::make_tuple(
true, BooleanFunction::Value::X, filter));
58 log_error(
"hal_simulator",
"cannot initialize sequential gates after the simulation was started.");
65 if (!m_is_initialized)
67 m_init_seq_gates.push_back(std::make_tuple(
false, value, filter));
71 log_error(
"hal_simulator",
"cannot initialize sequential gates after the simulation was started.");
81 for (
const Gate* gate : mSimulationInput->get_gates())
83 if (gate->get_type()->has_property(GateTypeProperty::ff))
85 GateType* gate_type = gate->get_type();
90 for (
Endpoint* ep : gate->get_fan_out_endpoints())
92 switch (ep->get_pin()->get_type())
94 case PinType::state: {
98 e.
time = m_current_time;
99 m_event_queue.push_back(e);
102 case PinType::neg_state: {
106 e.
time = m_current_time;
107 m_event_queue.push_back(e);
118 void NetlistSimulator::load_initial_values_from_netlist()
123 for (
const Gate* gate : mSimulationInput->get_gates())
125 if (gate->get_type()->has_property(GateTypeProperty::ff))
127 GateType* gate_type = gate->get_type();
132 if (init_component ==
nullptr)
138 if (!init_str.empty())
145 value = BooleanFunction::Value::ONE;
147 else if (init_str ==
"0")
149 value = BooleanFunction::Value::ZERO;
153 log_error(
"hal_simulator",
"init value of sequential gate '{}' (type '{}') is neither '1' or '0'.", gate->get_name(), gate_type->
get_name());
159 for (
Endpoint* ep : gate->get_fan_out_endpoints())
161 switch (ep->get_pin()->get_type())
163 case PinType::state: {
167 e.
time = m_current_time;
168 m_event_queue.push_back(e);
171 case PinType::neg_state: {
175 e.
time = m_current_time;
176 m_event_queue.push_back(e);
188 void NetlistSimulator::simulate(
u64 picoseconds)
190 if (!m_is_initialized)
195 prepare_clock_events(picoseconds);
197 process_events(m_current_time + picoseconds);
200 void NetlistSimulator::reset()
202 mSimulationInput->clear();
206 m_event_queue.clear();
207 m_is_initialized =
false;
210 void NetlistSimulator::set_simulation_state(
const Simulation& state)
212 m_simulation =
state;
215 const Simulation& NetlistSimulator::get_simulation_state()
const
220 void NetlistSimulator::set_iteration_timeout(
u64 iterations)
222 m_timeout_iterations = iterations;
225 u64 NetlistSimulator::get_simulation_timeout()
const
227 return m_timeout_iterations;
230 std::vector<WaveEvent> NetlistSimulator::get_simulation_events(
u32 netId)
const
237 for (
auto it = netEv.begin(); it != netEv.end(); ++it)
239 set_input(it->first, it->second);
251 m_successors.clear();
253 m_sim_gates_raw.clear();
255 std::unordered_map<const Gate*, SimulationGate*> sim_gates_map;
256 std::unordered_set<const Net*> all_nets;
257 std::map<const Net*, BooleanFunction::Value> init_events;
260 for (
const Gate* gate : mSimulationInput->get_gates())
262 SimulationGate* sim_gate_base =
nullptr;
264 if (gate->get_type()->has_property(GateTypeProperty::ff))
266 std::unique_ptr<SimulationGateFF> sim_gate_owner = std::make_unique<SimulationGateFF>(gate);
267 SimulationGateFF* sim_gate = sim_gate_owner.get();
268 sim_gate_base = sim_gate;
269 m_sim_gates.push_back(std::move(sim_gate_owner));
271 for (
const auto& [from_netlist, value, filter] : m_init_seq_gates)
273 if (!filter || filter(gate))
275 sim_gate->initialize(init_events, from_netlist, value);
279 else if (gate->get_type()->has_property(GateTypeProperty::ram))
281 std::unique_ptr<SimulationGateRAM> sim_gate_owner = std::make_unique<SimulationGateRAM>(gate);
282 SimulationGateRAM* sim_gate = sim_gate_owner.get();
283 sim_gate_base = sim_gate;
284 m_sim_gates.push_back(std::move(sim_gate_owner));
286 for (
const auto& [from_netlist, value, filter] : m_init_seq_gates)
288 if (!filter || filter(gate))
290 sim_gate->initialize(init_events, from_netlist, value);
294 else if (gate->get_type()->has_property(GateTypeProperty::combinational))
296 std::unique_ptr<SimulationGateCombinational> sim_gate_owner = std::make_unique<SimulationGateCombinational>(gate);
297 SimulationGateCombinational* sim_gate = sim_gate_owner.get();
298 sim_gate_base = sim_gate;
299 m_sim_gates.push_back(std::move(sim_gate_owner));
303 log_error(
"hal_simulator",
"no support for gate type {} of gate {}.", gate->get_type()->get_name(), gate->get_name());
304 m_successors.clear();
309 sim_gates_map.emplace(gate, sim_gate_base);
310 m_sim_gates_raw.push_back(sim_gate_base);
312 std::vector<Net*> out_nets = gate->get_fan_out_nets();
313 all_nets.insert(out_nets.begin(), out_nets.end());
316 const std::unordered_set<const Net*>& inets = mSimulationInput->get_input_nets();
317 all_nets.insert(inets.begin(), inets.end());
320 for (
auto net : all_nets)
322 if (
auto it = m_successors.find(
net); it != m_successors.end())
326 auto endpoints =
net->get_destinations();
327 std::unordered_map<Gate*, std::vector<const GatePin*>> affected_pins;
328 for (
auto ep : endpoints)
330 auto gate = ep->get_gate();
331 affected_pins[gate].push_back(ep->get_pin());
334 for (
auto it : affected_pins)
336 auto gate = it.first;
337 auto&
pins = it.second;
338 if (!mSimulationInput->contains_gate(gate))
342 auto sim_gate = sim_gates_map.at(gate);
343 m_successors[
net].emplace_back(sim_gate,
pins);
348 for (
auto g : mSimulationInput->get_gates())
350 if (g->is_gnd_gate())
352 for (
auto n : g->get_fan_out_nets())
354 init_events[n] = BooleanFunction::Value::ZERO;
357 else if (g->is_vcc_gate())
359 for (
auto n : g->get_fan_out_nets())
361 init_events[n] = BooleanFunction::Value::ONE;
367 for (
const auto& [
net, value] : init_events)
372 e.
time = m_current_time;
373 m_event_queue.push_back(e);
377 m_is_initialized =
true;
380 void NetlistSimulator::prepare_clock_events(
u64 picoseconds)
384 u64 base_time = m_current_time - (m_current_time % c.switch_time);
390 if (!c.start_at_zero)
396 while (time < picoseconds)
399 e.affected_net = c.clock_net;
401 e.time = base_time + time;
402 m_event_queue.push_back(e);
405 time += c.switch_time;
410 void NetlistSimulator::process_events(
u64 timeout)
412 measure_block_time(
"NetlistSimulator::process_events(" + std::to_string(timeout) +
")");
415 u64 total_iterations_for_one_timeslot = 0;
420 std::vector<SimulationGateSequential*> clocked_gates;
421 bool clocked_gates_processed =
false;
423 while (!m_event_queue.empty() || !clocked_gates.empty())
425 std::map<std::pair<const Net*, u64>, BooleanFunction::Value> new_events;
428 std::sort(m_event_queue.begin(), m_event_queue.end());
431 if (m_event_queue.empty() || m_current_time != m_event_queue[0].time)
434 if (!clocked_gates.empty() && !clocked_gates_processed)
436 for (SimulationGateSequential* clocked_gate : clocked_gates)
438 clocked_gate->clock(m_current_time, new_events);
440 clocked_gates.clear();
441 clocked_gates_processed =
true;
443 else if (m_event_queue.empty())
450 m_current_time = m_event_queue[0].time;
451 total_iterations_for_one_timeslot = 0;
452 clocked_gates_processed =
false;
458 if (m_current_time > timeout)
465 for (; processed < m_event_queue.size() && m_event_queue[processed].time <= m_current_time; ++processed)
467 auto&
event = m_event_queue[processed];
470 if (
auto it = m_simulation.m_events.find(event.affected_net); it != m_simulation.m_events.end())
473 if (it->second.back().new_value == event.new_value)
478 else if (it->second.back().time == event.time)
480 it->second.back().new_value =
event.new_value;
481 if (it->second.size() > 1 && it->second[it->second.size() - 2].new_value == event.new_value)
483 it->second.pop_back();
488 m_simulation.m_events[
event.affected_net].push_back(event);
493 m_simulation.m_events[
event.affected_net].push_back(event);
498 if (
auto suc_it = m_successors.find(event.affected_net); suc_it != m_successors.end())
500 for (
auto& [gate,
pins] : suc_it->second)
502 for (
auto& pin :
pins)
504 gate->m_input_values[pin->get_name()] =
event.new_value;
506 if (!gate->simulate(m_simulation, event, new_events))
508 clocked_gates.push_back(
static_cast<SimulationGateSequential*
>(gate));
515 total_iterations_for_one_timeslot += processed;
516 if (m_timeout_iterations > 0 && total_iterations_for_one_timeslot > m_timeout_iterations)
518 log_error(
"hal_simulator",
"reached iteration timeout of {} without advancing in time, aborting simulation. Please check for a combinational loop.", m_timeout_iterations);
523 m_event_queue.erase(m_event_queue.begin(), m_event_queue.begin() + processed);
526 m_event_queue.reserve(m_event_queue.size() + new_events.size());
527 for (
const auto& event_it : new_events)
530 e.affected_net = event_it.first.first;
531 e.time = event_it.first.second;
532 e.new_value = event_it.second;
533 e.id = m_id_counter++;
534 m_event_queue.push_back(e);
539 m_current_time = timeout;
544 if (behavior == AsyncSetResetBehavior::N)
546 return previous_output;
548 else if (behavior == AsyncSetResetBehavior::X)
550 return BooleanFunction::Value::X;
552 else if (behavior == AsyncSetResetBehavior::L)
554 return BooleanFunction::Value::ZERO;
556 else if (behavior == AsyncSetResetBehavior::H)
558 return BooleanFunction::Value::ONE;
560 else if (behavior == AsyncSetResetBehavior::T)
565 return BooleanFunction::Value::X;
568 bool NetlistSimulator::generate_vcd(
const std::filesystem::path& path,
u32 start_time,
u32 end_time, std::set<const Net*> nets)
const
570 if (mSimulationInput->get_gates().empty())
572 log_error(
"hal_simulator",
"no gates have been added to the simulator.");
576 if (m_simulation.get_events().empty())
578 log_error(
"hal_simulator",
"nothing has been simulated, cannot generate VCD.");
582 if (end_time > m_current_time)
584 log_error(
"hal_simulator",
"cannot generate VCD for {} ps, only {} ps have been simulated thus far.", end_time, m_current_time);
589 std::stringstream vcd;
590 auto t = std::time(
nullptr);
591 auto tm = *std::localtime(&t);
592 vcd <<
"$version Generated by HAL $HAL" << std::endl;
593 vcd <<
"$date " << std::put_time(&tm,
"%d-%m-%Y %H-%M-%S") << std::endl;
594 vcd <<
"$timescale 1ps $end" << std::endl;
597 vcd <<
"$scope module TOP $end" << std::endl;
599 std::unordered_map<const Net*, std::vector<WaveEvent>> events = m_simulation.get_events();
600 std::vector<const Net*> simulated_nets;
602 for (
auto net_changes : events)
604 const Net*
net = net_changes.first;
605 if ((
net !=
nullptr) && (nets.empty() || nets.find(
net) != nets.end()))
608 vcd <<
"$var wire 1 n" <<
net->get_id() <<
" " <<
net->get_name() <<
" $end" << std::endl;
611 simulated_nets.push_back(
net);
615 vcd <<
"$upscope $end" << std::endl;
616 vcd <<
"$enddefinitions $end" << std::endl;
618 std::unordered_map<const Net*, BooleanFunction::Value> change_tracker;
619 vcd <<
"#" << 0 << std::endl;
621 std::map<u32, std::map<const Net*, BooleanFunction::Value>> time_to_changes_map;
623 std::unordered_map<const Net*, std::vector<WaveEvent>> event_tracker = m_simulation.get_events();
625 for (
const auto& simulated_net : simulated_nets)
627 std::vector<WaveEvent> net_events = event_tracker.at(simulated_net);
629 u32 initial_time = 0;
631 for (
const auto& event_it : net_events)
633 u32 event_time = event_it.time;
634 if (initial_time == event_time || ((event_time > initial_time) && (event_time < start_time)))
636 initial_time = event_time;
637 initial_value = event_it.new_value;
639 if (event_time > start_time && event_time < end_time)
641 time_to_changes_map[event_it.time][simulated_net] = event_it.new_value;
645 time_to_changes_map[start_time][simulated_net] = initial_value;
648 u32 traces_count = 0;
650 for (
const auto& [event_time, changed_nets] : time_to_changes_map)
653 vcd <<
"#" << event_time << std::endl;
655 for (
const auto& [
net, value] : changed_nets)
658 if (value == BooleanFunction::Value::X)
660 vcd <<
"xn" <<
net->get_id() << std::endl;
662 else if (value == BooleanFunction::Value::ONE)
664 vcd <<
"1n" <<
net->get_id() << std::endl;
666 else if (value == BooleanFunction::Value::ZERO)
668 vcd <<
"0n" <<
net->get_id() << std::endl;
670 else if (value == BooleanFunction::Value::Z)
672 log_error(
"hal_simulator",
"signal value of 'Z' for net with ID {} at {} ps is currently not supported.",
net->get_id(), event_time);
677 log_error(
"hal_simulator",
"signal value for net with ID {} at {} ps is unknown.",
net->get_id(), event_time);
682 vcd <<
"#" << traces_count << std::endl;
684 std::ofstream ofs(path);
687 log_error(
"hal_simulator",
"could not open file '{}' for writing.", path.string());
Value
represents the type of the node
const std::string & get_name() const
const std::string & get_init_category() const
const std::vector< std::string > & get_init_identifiers() const
ComponentType get_type() const override
std::vector< WaveEvent > get_events_by_net_id(u32 netId, bool *found=nullptr) const
#define log_error(channel,...)
BooleanFunction::Value toggle(BooleanFunction::Value v)
BooleanFunction::Value process_clear_preset_behavior(AsyncSetResetBehavior behavior, BooleanFunction::Value previous_output)
std::string enum_to_string(T e)
std::vector< PinInformation > pins
#define measure_block_time(X)
BooleanFunction::Value new_value