The Sparta Modeling Framework
Loading...
Searching...
No Matches
Fetch.cpp
Go to the documentation of this file.
1// <Fetch.cpp> -*- C++ -*-
2
7
8#include <algorithm>
9#include "Fetch.hpp"
10
12
13namespace core_example
14{
15 const char * Fetch::name = "fetch";
16
17 // Dummy opcodes, but based on a really small piece of PowerPC...
18 static std::vector<ExampleInst::StaticInfo> dummy_opcodes =
19 {
20 { {0x7c01f214, 0xffffffff, {}, "add.", 0 }, ExampleInst::TargetUnit::ALU0, 1, false},
21 { {0x7c6f0f10, 0xffffffff, {}, "cntlzw", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
22 { {0x7c800000, 0xffffffff, {}, "add", 0 }, ExampleInst::TargetUnit::ALU0, 1, false},
23 { {0x7c700000, 0xffffffff, {}, "subf.", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
24 { {0x7c000000, 0xffffffff, {}, "and", 0 }, ExampleInst::TargetUnit::ALU0, 1, false},
25 { {0x7c000000, 0xffffffff, {}, "and", 0 }, ExampleInst::TargetUnit::ALU0, 1, false},
26 { {0x7c000710, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 1, false},
27 { {0x7c700000, 0xffffffff, {}, "cmp", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
28 { {0x7c700010, 0xffffffff, {}, "cmn", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
29 { {0x7c500000, 0xffffffff, {}, "cmp", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
30 { {0x7c500000, 0xffffffff, {}, "cmp", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
31 { {0x7c400010, 0xffffffff, {}, "sub", 0 }, ExampleInst::TargetUnit::ALU1, 1, false},
32 { {0xfc800500, 0xffffffff, {}, "fabs",0 }, ExampleInst::TargetUnit::FPU, 5, false},
33 { {0xfc000700, 0xffffffff, {}, "fctid.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
34 { {0xfc200d00, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
35 { {0xfc800700, 0xffffffff, {}, "fadd.",0 }, ExampleInst::TargetUnit::FPU, 5, false},
36 { {0xfcb10300, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
37 { {0xfcb00ac0, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
38 { {0xfc000800, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
39 { {0xfc000d00, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
40 { {0xfc300a00, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 5, false},
41 { {0xfc800400, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 10, false},
42 { {0xfc800000, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 1, false},
43 { {0xfc800100, 0xffffffff, {}, "fadd.", 0 }, ExampleInst::TargetUnit::FPU, 1, false},
44 { {0xfc000110, 0xffffffff, {}, "fdiv", 0 }, ExampleInst::TargetUnit::FPU, 20, false},
45 { {0xfc800030, 0xffffffff, {}, "fdiv.", 0 }, ExampleInst::TargetUnit::FPU, 30, false},
46 { {0xfc100000, 0xffffffff, {}, "sync", 0 }, ExampleInst::TargetUnit::ROB, 1, false},
47 { {0x7ea00010, 0xffffffff, {}, "lwx", 0 }, ExampleInst::TargetUnit::LSU, 10, false},
48 { {0xfca00030, 0xffffffff, {}, "stw", 0 }, ExampleInst::TargetUnit::LSU, 10, true}
49 };
50
51 // Fetch a random instruction or MaxIPC
52 template<bool MaxIPC>
53 void Fetch::fetchInstruction_()
54 {
55 const uint32_t upper = std::min(credits_inst_queue_, num_insts_to_fetch_);
56
57 // Nothing to send. Don't need to schedule this again.
58 if(upper == 0) { return; }
59
60 InstGroup insts_to_send;
61 for(uint32_t i = 0; i < upper; ++i) {
62 ExampleInstPtr ex_inst;
63 if(MaxIPC) {
64 ex_inst =
65 sparta::allocate_sparta_shared_pointer<ExampleInst>(example_inst_allocator,
66 dummy_opcodes[i], getClock());
67 // This can be done instead, but you will lose about
68 // ~20% performance in an experiment running 5M
69 // instructions
70 //ex_inst.reset(new ExampleInst(dummy_opcodes[i], getClock()));
71 }
72 else {
73 ex_inst =
74 sparta::allocate_sparta_shared_pointer<ExampleInst>(example_inst_allocator,
75 dummy_opcodes[rand() % dummy_opcodes.size()], getClock());
76 }
77 ex_inst->setUniqueID(++next_inst_id_);
78 ex_inst->setVAdr(vaddr_);
79 ex_inst->setSpeculative(speculative_path_);
80 insts_to_send.emplace_back(ex_inst);
81
83 info_logger_ << "RANDOM: Sending: " << ex_inst << " down the pipe";
84 }
85 speculative_path_ = (ex_inst->getUnit() == ExampleInst::TargetUnit::ROB);
86
87 vaddr_ += 4;
88 }
89
90
91 out_fetch_queue_write_.send(insts_to_send);
92
93 credits_inst_queue_ -= upper;
94 if(credits_inst_queue_ > 0) {
95 fetch_inst_event_->schedule(1);
96 }
97
99 info_logger_ << "Fetch: send num_inst=" << insts_to_send.size()
100 << " instructions, remaining credit=" << credits_inst_queue_;
101 }
102 }
103
105 const FetchParameterSet * p) :
106 sparta::Unit(node),
107 num_insts_to_fetch_(p->num_to_fetch),
108 next_pc_(node, "next_pc", &vaddr_)
109 {
110 in_fetch_queue_credits_.
111 registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(Fetch, receiveFetchQueueCredits_, uint32_t));
112
113 if (p->fetch_max_ipc == true) {
114 fetch_inst_event_.reset(new sparta::SingleCycleUniqueEvent<>(&unit_event_set_, "fetch_max_ipc",
115 CREATE_SPARTA_HANDLER(Fetch, fetchInstruction_<true>)));
116 // Schedule a single event to start reading -- not needed since receiveFetchQueueCredits launches fetch_instruction_event.
117 //sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(Fetch, fetchInstruction_<true>));
118 }
119 else {
120 fetch_inst_event_.reset(new sparta::SingleCycleUniqueEvent<>(&unit_event_set_, "fetch_random",
121 CREATE_SPARTA_HANDLER(Fetch, fetchInstruction_<false>)));
122 // Schedule a single event to start reading from a trace file -- not needed since receiveFetchQueueCredits launches fetch_instruction_event.
123 //sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(Fetch, fetchInstruction_<false>));
124 }
125
126 in_fetch_flush_redirect_.registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(Fetch, flushFetch_, uint64_t));
127
128 srand(p->inst_rand_seed);
129 }
130
131 // Called when decode has room
132 void Fetch::receiveFetchQueueCredits_(const uint32_t & dat) {
133 credits_inst_queue_ += dat;
134
136 info_logger_ << "Fetch: receive num_decode_credits=" << dat
137 << ", total decode_credits=" << credits_inst_queue_;
138 }
139
140 // Schedule a fetch event this cycle
141 fetch_inst_event_->schedule(sparta::Clock::Cycle(0));
142 }
143
144 // Called from Retire via in_fetch_flush_redirect_ port
145 void Fetch::flushFetch_(const uint64_t & new_addr) {
147 info_logger_ << "Fetch: receive flush on new_addr=0x"
148 << std::hex << new_addr << std::dec;
149 }
150
151 // New address to fetch from
152 vaddr_ = new_addr;
153
154 // Cancel all previously sent instructions on the outport
155 out_fetch_queue_write_.cancel();
156
157 // No longer speculative
158 speculative_path_ = false;
159 }
160
161}
Definition of the CoreModel Fetch unit.
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
#define CREATE_SPARTA_HANDLER_WITH_DATA(clname, meth, dataT)
#define CREATE_SPARTA_HANDLER(clname, meth)
File that defines the StartupEvent class.
Parameters for Fetch model.
Definition Fetch.hpp:38
Fetch(sparta::TreeNode *name, const FetchParameterSet *p)
Constructor for Fetch.
Definition Fetch.cpp:104
static const char * name
Name of this resource. Required by sparta::UnitFactory.
Definition Fetch.hpp:76
uint32_t cancel()
Cancel all outstanding port sends regardless of criteria.
Definition DataPort.hpp:193
void send(const DataT &dat, sparta::Clock::Cycle rel_time=0)
Send data to bound receivers.
Definition DataPort.hpp:145
void registerConsumerHandler(const SpartaHandler &handler)
Register a handler to this Port (must be Direction::IN) to handle data arrival.
Definition Port.hpp:337
const Clock * getClock() const
An event that can only be schedule one cycle into the future.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
sparta::EventSet unit_event_set_
The Unit's event set.
Definition Unit.hpp:114
log::MessageSource info_logger_
Default info logger.
Definition Unit.hpp:156
Macros for handling exponential backoff.