16 #include "llvm/Support/Format.h"
17 #include "llvm/Support/raw_ostream.h"
29 return std::to_string(time) +
"ps " + std::to_string(delta) +
"d " +
30 std::to_string(eps) +
"e";
37 std::string Signal::toHexString()
const {
39 raw_string_ostream ss(ret);
41 for (
int i = size - 1; i >= 0; --i) {
42 ss << format_hex_no_prefix(static_cast<int>(
value[i]), 2);
47 std::string Signal::toHexString(
unsigned elemIndex)
const {
48 assert(elements.size() > 0 &&
"the signal type has to be tuple or array!");
49 auto elemSize = elements[elemIndex].second;
50 auto *ptr =
value + elements[elemIndex].first;
52 raw_string_ostream ss(ret);
54 for (
int i = elemSize - 1; i >= 0; --i) {
55 ss << format_hex_no_prefix(static_cast<int>(ptr[i]), 2);
71 bool Slot::operator>(
const Slot &rhs)
const {
return rhs.
time < time; }
73 void Slot::insertChange(
int index,
int bitOffset, uint8_t *bytes,
76 auto size = llvm::divideCeil(
width, 8);
78 APInt buffer(
width, 0);
79 llvm::LoadIntFromMemory(buffer, bytes, size);
80 auto offsetBufferPair = std::make_pair(bitOffset, buffer);
82 if (changesSize >= buffers.size()) {
85 buffers.push_back(offsetBufferPair);
88 buffers[changesSize] = offsetBufferPair;
93 changes.push_back(std::make_pair(index, changesSize));
97 void Slot::insertChange(
unsigned inst) { scheduled.push_back(inst); }
102 void UpdateQueue::insertOrUpdate(
Time time,
int index,
int bitOffset,
103 uint8_t *bytes,
unsigned width) {
104 auto &slot = getOrCreateSlot(time);
105 slot.insertChange(index, bitOffset, bytes,
width);
108 void UpdateQueue::insertOrUpdate(
Time time,
unsigned inst) {
109 auto &slot = getOrCreateSlot(time);
110 slot.insertChange(inst);
114 auto &top = begin()[topSlot];
117 if (!top.unused && time == top.
time) {
125 if (events > 0 && top.time < time) {
126 for (
size_t i = 0, e = size(); i < e; ++i) {
127 if (time == begin()[i].time) {
134 if (!unused.empty()) {
135 auto firstUnused = unused.pop_back_val();
136 auto &newSlot = begin()[firstUnused];
142 if (top.unused || time < top.
time)
143 topSlot = firstUnused;
150 push_back(
Slot(time));
154 if (top.unused || time < top.
time)
155 topSlot = size() - 1;
161 const Slot &UpdateQueue::top() {
162 assert(topSlot < size() &&
"top is pointing out of bounds!");
166 auto &top = begin()[topSlot];
167 llvm::sort(top.changes.begin(), top.changes.begin() + top.changesSize);
171 void UpdateQueue::pop() {
173 auto &curr = begin()[topSlot];
175 curr.changesSize = 0;
176 curr.scheduled.clear();
177 curr.changes.clear();
182 unused.push_back(topSlot);
185 topSlot = std::distance(
187 std::min_element(begin(), end(), [](
const auto &a,
const auto &b) {
190 return !a.unused && (a < b || b.unused);
198 Instance::~Instance() {
199 std::free(procState);
201 std::free(entityState);
202 entityState =
nullptr;
210 for (
auto &inst : instances) {
211 if (inst.procState) {
212 std::free(inst.procState->senses);
218 assert(!queue.empty() &&
"the event queue is empty");
219 Slot pop = queue.top();
224 void State::pushQueue(
Time t,
unsigned inst) {
225 Time newTime = time + t;
226 queue.insertOrUpdate(newTime, inst);
227 instances[inst].expectedWakeup = newTime;
230 llvm::SmallVectorTemplateCommon<Instance>::iterator
231 State::getInstanceIterator(std::string instName) {
233 std::find_if(instances.begin(), instances.end(),
234 [&](
const auto &inst) { return instName == inst.name; });
236 assert(it != instances.end() &&
"instance does not exist!");
241 int State::addSignal(std::string name, std::string owner) {
242 signals.push_back(
Signal(name, owner));
243 return signals.size() - 1;
246 void State::addProcPtr(std::string name,
ProcState *procStatePtr) {
247 auto it = getInstanceIterator(name);
250 procStatePtr->
inst = it - instances.begin();
251 (*it).procState = procStatePtr;
254 int State::addSignalData(
int index, std::string owner, uint8_t *
value,
256 auto it = getInstanceIterator(owner);
258 uint64_t globalIdx = (*it).sensitivityList[index + (*it).nArgs].globalIndex;
259 auto &sig = signals[globalIdx];
262 sig.store(
value, size);
266 for (
auto inst : signals[globalIdx].getTriggeredInstanceIndices()) {
267 for (
auto &
detail : instances[inst].sensitivityList) {
268 if (
detail.globalIndex == globalIdx) {
269 detail.value = sig.getValue();
276 void State::addSignalElement(
unsigned index,
unsigned offset,
unsigned size) {
277 signals[index].pushElement(std::make_pair(offset, size));
280 void State::dumpSignal(llvm::raw_ostream &out,
int index) {
281 auto &sig = signals[index];
282 for (
auto inst : sig.getTriggeredInstanceIndices()) {
283 out << time.toString() <<
" " << instances[inst].path <<
"/"
284 << sig.getName() <<
" " << sig.toHexString() <<
"\n";
288 void State::dumpLayout() {
289 llvm::errs() <<
"::------------------- Layout -------------------::\n";
290 for (
const auto &inst : instances) {
292 llvm::errs() <<
"---path: " << inst.path <<
"\n";
293 llvm::errs() <<
"---isEntity: " << inst.isEntity <<
"\n";
295 for (
auto in : inst.sensitivityList) {
300 llvm::errs() <<
"::----------------------------------------------::\n";
303 void State::dumpSignalTriggers() {
304 llvm::errs() <<
"::------------- Signal information -------------::\n";
305 for (
size_t i = 0, e = signals.size(); i < e; ++i) {
306 llvm::errs() << signals[i].getOwner() <<
"/" << signals[i].getName()
308 for (
auto trig : signals[i].getTriggeredInstanceIndices()) {
313 llvm::errs() <<
"::----------------------------------------------::\n";
assert(baseType &&"element must be base type")
constexpr const char * toString(Flow flow)
The simulator's internal representation of a signal.
The simulator's internal representation of time.
uint64_t time
Simulation real time.
bool operator<(const AppIDPath &a, const AppIDPath &b)
mlir::raw_indented_ostream & errs()
State structure for process persistence across suspension.
The simulator's internal representation of one queue slot.