-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInstructionCache.h
More file actions
106 lines (81 loc) · 3.51 KB
/
Copy pathInstructionCache.h
File metadata and controls
106 lines (81 loc) · 3.51 KB
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#pragma once
#include "../Request.h"
#include "Cache.h"
#include "Policy/FIFOPolicy.h"
#include <memory>
#include <systemc>
/**
* This instruction cache is the provider of instructions in our model. Since defining an encoding for the instructions
* was out of scope for this project, the instruction cache simply reads a dummy 1 byte from RAM / its internal
* cacheline and subsequently "decodes it" by using its internal instruction store to look up the corresponding
* instruction.
*
* For more information on how the internal cache works see Cache.cpp
*/
SC_MODULE(InstructionCache) {
private:
const std::uint32_t cacheLineNum;
const std::uint32_t cacheLineSize;
const std::uint32_t cacheLatency;
Cache<MappingType::Direct> cache{"Cache", cacheLineNum, cacheLineSize, cacheLatency, nullptr};
std::vector<Request> instructions;
SC_CTOR(InstructionCache);
public:
sc_core::sc_in<bool> SC_NAMED(clock);
// Instruction Cache -> CPU
sc_core::sc_out<Request> SC_NAMED(instructionBus);
sc_core::sc_out<bool> SC_NAMED(instrReadyBus);
// CPU -> Instruction Cache
sc_core::sc_in<bool> SC_NAMED(validInstrRequestBus);
sc_core::sc_in<std::uint32_t> SC_NAMED(pcBus);
// Cache -> RAM
sc_core::sc_out<std::uint32_t> SC_NAMED(memoryAddrBus);
sc_core::sc_out<std::uint32_t> SC_NAMED(memoryDataOutBus);
sc_core::sc_out<bool> SC_NAMED(memoryWeBus);
sc_core::sc_out<bool> SC_NAMED(memoryValidRequestBus);
// RAM -> Cache
sc_core::sc_in<sc_dt::sc_bv<128>> SC_NAMED(memoryDataInBus);
sc_core::sc_in<bool> SC_NAMED(memoryReadyBus);
private:
sc_core::sc_signal<bool> SC_NAMED(instrWeSignal, false); // always false
sc_core::sc_signal<std::uint32_t> SC_NAMED(instrDataInSignal); // never read
// All other ports can be directly connected to internal cache
sc_core::sc_signal<std::uint32_t> SC_NAMED(cacheDataOutSignal);
sc_core::sc_signal<bool> SC_NAMED(validInstrRequestSignal);
public:
InstructionCache(sc_core::sc_module_name name, std::uint32_t cacheLines, std::uint32_t cacheLineSize,
std::uint32_t cacheLatency, std::vector<Request> instructions)
: sc_module{name}, cacheLineNum{cacheLines}, cacheLineSize{cacheLineSize}, cacheLatency{cacheLatency},
instructions{instructions} {
using namespace sc_core;
cache.clock(clock);
cache.memoryAddrBus(memoryAddrBus);
cache.memoryDataOutBus(memoryDataOutBus);
cache.memoryWeBus(memoryWeBus);
cache.memoryValidRequestBus(memoryValidRequestBus);
cache.memoryReadyBus(memoryReadyBus);
cache.memoryDataInBus(memoryDataInBus);
cache.cpuDataOutBus(cacheDataOutSignal); // dummy - gets discarded
cache.ready(instrReadyBus);
cache.cpuAddrBus(pcBus);
cache.cpuDataInBus(instrDataInSignal);
cache.cpuWeBus(instrWeSignal);
cache.cpuValidRequest(validInstrRequestSignal);
SC_METHOD(provideInstruction);
sensitive << cache.ready;
SC_METHOD(interceptTooHighPCVal);
sensitive << pcBus << validInstrRequestBus;
}
#ifdef STRICT_INSTRUCTION_ORDER
void setMemoryLatency(std::uint32_t latency) { cache.setMemoryLatency(latency); }
#endif
private:
void interceptTooHighPCVal() {
validInstrRequestSignal.write(validInstrRequestBus.read() && pcBus.read() < instructions.size());
}
void provideInstruction() {
if (cache.ready.read()) {
instructionBus.write(instructions[pcBus.read()]);
}
}
};