blob: 0eaebd5e108e5c1535f042fbcb52c0b7fe3e2d4e (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
#pragma once
#include <cassert>
#include <cstdint>
#include <cstring>
#include <map>
#include <optional>
#include <utility>
#include "frontend/bundle.h"
#include "infra/pipetrace.h"
#include "infra/sim.h"
#include "memory/dram.h"
namespace frontend {
struct fetch : public infra::sim {
struct restart {
unsigned int new_generation;
std::uint64_t previous_line_address;
std::uint64_t new_next_line_address;
};
infra::port<restart> restartp;
infra::port<memory::dram::command> *commandp = nullptr;
infra::port<memory::dram::response> responsep;
infra::port<bundle> *bundlep = nullptr;
unsigned int generation = 0;
std::uint64_t next_line_address = 0;
// FIXME make prediction table finite
std::map<std::uint64_t, std::uint64_t> predictor;
bool fill_request_sent = false;
void clock() {
if (restartp.can_read()) {
auto r = restartp.read();
generation = r.new_generation;
next_line_address = r.new_next_line_address;
fill_request_sent = false;
if (r.new_next_line_address == r.previous_line_address || r.new_next_line_address == r.previous_line_address + 1)
predictor.erase(r.previous_line_address);
else
predictor[r.previous_line_address] = r.new_next_line_address;
}
if (fill_request_sent && responsep.can_read() && bundlep->can_write()) {
auto r = responsep.read();
if (r.line_address == next_line_address) {
bundle b;
b.transaction = r.transaction;
b.generation = generation;
b.line_address = next_line_address;
if (auto p = predictor.find(next_line_address); p != predictor.end())
b.next_line_address = p->second;
else
b.next_line_address = next_line_address + 1;
next_line_address = b.next_line_address;
pte(b.transaction, "", fmt::format("next fetch line {:x}", next_line_address));
b.data = std::move(r.data);
bundlep->write(std::move(b));
fill_request_sent = false;
}
}
if (!fill_request_sent && commandp->can_write()) {
memory::dram::command c;
c.transaction = infra::pt::toplevel();
pte(c.transaction, "F", fmt::format("fetch gen={}", generation));
c.line_address = next_line_address;
c.responsep = &responsep;
commandp->write(std::move(c));
fill_request_sent = true;
}
if (!fill_request_sent)
responsep.discard();
}
};
}
|