Rodrigo Arias
354f2f50eb
Until now, emulation models were always being registered via probe(), which causes the emulator to initialize all the channels. To reduce the overhead, the channels were not connected or registered in the bay until the first event of that model was received. This delayed connect was causing issues in muxes where the newly connected model required refreshing the touched channels. Which in turn was causing unexpected PRV events. By determining which models we need to enable, we can remove the delayed connect mechanism and just enable those models at initialization time, and connect the channels.
164 lines
3.8 KiB
C
164 lines
3.8 KiB
C
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include "compat.h"
|
|
#include "instr.h"
|
|
#include "ovni.h"
|
|
|
|
static void
|
|
emit_jumbo(uint8_t *buf, size_t size, int64_t clock)
|
|
{
|
|
struct ovni_ev ev = {0};
|
|
ovni_ev_set_mcv(&ev, "OUj");
|
|
ovni_ev_set_clock(&ev, clock);
|
|
ovni_ev_jumbo_emit(&ev, buf, size);
|
|
}
|
|
|
|
static void
|
|
emit(char *mcv, int64_t clock)
|
|
{
|
|
struct ovni_ev ev = {0};
|
|
ovni_ev_set_mcv(&ev, mcv);
|
|
ovni_ev_set_clock(&ev, clock);
|
|
ovni_ev_emit(&ev);
|
|
}
|
|
|
|
static void
|
|
fill(long room)
|
|
{
|
|
/* Flush the buffer so we begin with a known size: the two flush
|
|
* events */
|
|
ovni_flush();
|
|
|
|
size_t ev_size = sizeof(struct ovni_ev_header);
|
|
|
|
/* Skip the jumbo event header and payload size */
|
|
size_t header = ev_size + 4;
|
|
|
|
size_t payload_size = OVNI_MAX_EV_BUF - room - header;
|
|
uint8_t *payload_buf = calloc(1, payload_size);
|
|
|
|
/* Fill the stream buffer */
|
|
int64_t t = ovni_clock_now();
|
|
emit_jumbo(payload_buf, payload_size, t);
|
|
|
|
/* Leave some room to prevent clashes */
|
|
sleep_us(100);
|
|
}
|
|
|
|
static void
|
|
test_flush_after_sort(void)
|
|
{
|
|
/* In this test we check with the flush events OF[ and OF]
|
|
* immediately after the sort region opening event OU[.
|
|
*
|
|
* $ ovnidump thread.150439.obs | cut -c -72
|
|
* ovnidump: INFO: loaded 1 streams
|
|
* 1778730985500133 +1778730985500133 OHx :00:00:00:00:ff:ff:ff:ff:00:0
|
|
* 1778730985503455 +3322 OF[
|
|
* 1778730985508228 +4773 OF]
|
|
* 1778730985666648 +158420 OUj :cc:ff:1f:00:00:00:00:00:00:00:00:00
|
|
* 1778730985666649 +1 OU[
|
|
* 1778730987234771 +1568122 OF[ <-- here we inject the
|
|
* 1778730988411065 +1176294 OF] flush events
|
|
* 1778730985666550 -2744515 KCI
|
|
* 1778730985666551 +1 KCO
|
|
* 1778730985666652 +101 OU]
|
|
* 1778730988411997 +2745345 OHe
|
|
*/
|
|
|
|
/* Skip the two flush events and leave room for OU[ */
|
|
fill(3 * sizeof(struct ovni_ev_header));
|
|
|
|
int64_t t = ovni_clock_now();
|
|
|
|
/* Emit the opening of the sort region */
|
|
emit("OU[", t++);
|
|
|
|
/* This should cause the stream to be flush and inject the two
|
|
* extra events OF[ and OF] */
|
|
emit("KCO", t++ - 100);
|
|
|
|
/* Finish the kernel event */
|
|
emit("KCI", t++ - 100);
|
|
|
|
/* Finish the sort region */
|
|
emit("OU]", ovni_clock_now());
|
|
}
|
|
|
|
static void
|
|
test_unsorted(void)
|
|
{
|
|
/* Test unsorted events in the sorting region */
|
|
|
|
sleep_us(100); /* Make room */
|
|
int64_t t = ovni_clock_now();
|
|
emit("OU[", t);
|
|
emit("KCI", t + 2 - 100); /* out of order */
|
|
emit("KCO", t + 1 - 100);
|
|
emit("OU]", t + 3);
|
|
}
|
|
|
|
static void
|
|
test_overlap(void)
|
|
{
|
|
/* Test overlapping events among regions */
|
|
|
|
int64_t t = ovni_clock_now();
|
|
/* Round time next 1 microsecond to be easier to read */
|
|
t += 1000 - (t % 1000);
|
|
|
|
emit("OU[", t + 20);
|
|
emit("KCO", t + 10);
|
|
emit("KCI", t + 11);
|
|
emit("OU]", t + 21);
|
|
emit("OU[", t + 22);
|
|
emit("KCO", t + 12); /* These two shold appear in the first region */
|
|
emit("KCI", t + 13);
|
|
emit("OU]", t + 23);
|
|
}
|
|
|
|
static void
|
|
test_overlap_flush(void)
|
|
{
|
|
/* Test overlapping events with flush events too */
|
|
|
|
/* Skip the two flush events and leave room for OU[ */
|
|
sleep_us(100);
|
|
fill(5 * sizeof(struct ovni_ev_header));
|
|
int64_t t = ovni_clock_now();
|
|
|
|
/* Round time next 1 microsecond to be easier to read */
|
|
t += 1000 - (t % 1000);
|
|
|
|
emit("OU[", t + 20);
|
|
emit("KCO", t + 10);
|
|
emit("KCI", t + 11);
|
|
emit("OU]", t + 21);
|
|
/* We need realistic clock due to incoming flush */
|
|
emit("OU[", ovni_clock_now());
|
|
/* Flush here */
|
|
emit("KCO", t + 12);
|
|
emit("KCI", t + 13);
|
|
emit("OU]", ovni_clock_now());
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
/* This program tests various cases in which flush events are placed in
|
|
* the sorting region, disrupting the order. */
|
|
|
|
instr_start(0, 1);
|
|
instr_require("kernel");
|
|
test_flush_after_sort();
|
|
test_unsorted();
|
|
test_overlap();
|
|
test_overlap_flush();
|
|
instr_end();
|
|
|
|
return 0;
|
|
}
|