|
1 | 1 | #include "rob.h" |
2 | 2 | #include "policy.h" |
| 3 | +#include <atomic> |
3 | 4 | #include <cxxopts.hpp> |
4 | 5 | #include <fstream> |
| 6 | +#include <future> |
5 | 7 | #include <iostream> |
| 8 | +#include <mutex> |
| 9 | +#include <queue> |
6 | 10 | #include <ranges> |
7 | 11 | #include <spdlog/cfg/env.h> |
8 | 12 | #include <sstream> |
| 13 | +#include <thread> |
| 14 | +#include <vector> |
9 | 15 |
|
10 | 16 | Helper helper{}; |
11 | 17 | CXLController *controller; |
@@ -123,6 +129,86 @@ InstructionGroup parseGroup(const std::vector<std::string> &group) { |
123 | 129 | } |
124 | 130 | return ig; |
125 | 131 | } |
| 132 | +void parseInParallel(std::ifstream &file, std::vector<InstructionGroup> &instructions) { |
| 133 | + std::mutex queueMutex; |
| 134 | + std::condition_variable cv; |
| 135 | + std::queue<std::vector<std::string>> groupsQueue; |
| 136 | + std::atomic<bool> done{false}; |
| 137 | + std::vector<std::string> groupLines; |
| 138 | + |
| 139 | + // 创建解析线程池 |
| 140 | + const int numThreads = std::thread::hardware_concurrency(); |
| 141 | + std::vector<std::thread> parseThreads; |
| 142 | + std::mutex resultsMutex; |
| 143 | + |
| 144 | + // 消费者线程函数 |
| 145 | + auto parseWorker = [&]() { |
| 146 | + while (true) { |
| 147 | + std::vector<std::string> group; |
| 148 | + { |
| 149 | + std::unique_lock<std::mutex> lock(queueMutex); |
| 150 | + cv.wait(lock, [&]() { return !groupsQueue.empty() || done; }); |
| 151 | + if (groupsQueue.empty() && done) |
| 152 | + break; |
| 153 | + group = std::move(groupsQueue.front()); |
| 154 | + groupsQueue.pop(); |
| 155 | + } |
| 156 | + |
| 157 | + auto result = parseGroup(group); |
| 158 | + if (result.retireTimestamp != 0) { |
| 159 | + std::lock_guard<std::mutex> lock(resultsMutex); |
| 160 | + instructions.emplace_back(std::move(result)); |
| 161 | + } |
| 162 | + } |
| 163 | + }; |
| 164 | + |
| 165 | + // 启动消费者线程 |
| 166 | + for (int i = 0; i < numThreads; ++i) { |
| 167 | + parseThreads.emplace_back(parseWorker); |
| 168 | + } |
| 169 | + |
| 170 | + // 生产者部分 - 主线程 |
| 171 | + for (const std::string &line : std::ranges::istream_view<std::string>(file)) { |
| 172 | + if (line.rfind("O3PipeView:fetch:", 0) == 0) { |
| 173 | + if (!groupLines.empty()) { |
| 174 | + { |
| 175 | + std::lock_guard<std::mutex> lock(queueMutex); |
| 176 | + groupsQueue.push(groupLines); |
| 177 | + } |
| 178 | + cv.notify_one(); |
| 179 | + groupLines.clear(); |
| 180 | + } |
| 181 | + } |
| 182 | + if (!line.empty()) { |
| 183 | + groupLines.push_back(line); |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | + // 处理最后一组 |
| 188 | + if (!groupLines.empty()) { |
| 189 | + { |
| 190 | + std::lock_guard<std::mutex> lock(queueMutex); |
| 191 | + groupsQueue.push(std::move(groupLines)); |
| 192 | + } |
| 193 | + cv.notify_one(); |
| 194 | + } |
| 195 | + |
| 196 | + // 通知所有消费者线程完成 |
| 197 | + { |
| 198 | + std::lock_guard<std::mutex> lock(queueMutex); |
| 199 | + done = true; |
| 200 | + } |
| 201 | + cv.notify_all(); |
| 202 | + |
| 203 | + // 等待所有线程完成 |
| 204 | + for (auto &thread : parseThreads) { |
| 205 | + thread.join(); |
| 206 | + } |
| 207 | + |
| 208 | + // 排序结果 |
| 209 | + std::sort(instructions.begin(), instructions.end(), |
| 210 | + [](InstructionGroup &a, InstructionGroup &b) { return a.cycleCount < b.cycleCount; }); |
| 211 | +} |
126 | 212 |
|
127 | 213 | int main(int argc, char *argv[]) { |
128 | 214 | spdlog::cfg::load_env_levels(); |
@@ -194,38 +280,9 @@ int main(int argc, char *argv[]) { |
194 | 280 | return 1; |
195 | 281 | } |
196 | 282 |
|
197 | | - std::vector<std::string> groupLines; |
| 283 | + // std::vector<std::string> groupLines; |
198 | 284 | std::vector<InstructionGroup> instructions; |
199 | | - |
200 | | - // Read the file line by line using std::ranges::istream_view. |
201 | | - for (const std::string &line : std::ranges::istream_view<std::string>(file)) { |
202 | | - // If the line starts with "O3PipeView:fetch:" then it's the start of a new group. |
203 | | - if (line.rfind("O3PipeView:fetch:", 0) == 0) { |
204 | | - // If we have an existing group, process it. |
205 | | - if (!groupLines.empty()) { |
206 | | - instructions.emplace_back(parseGroup(groupLines)); |
207 | | - if (instructions.back().retireTimestamp == 0) { |
208 | | - // auto& back = instructions.back(); |
209 | | - // std::cout << "throwing out: " << back.address << back.cycleCount << "[]" << back.retireTimestamp |
210 | | - // << std::endl; |
211 | | - instructions.pop_back(); |
212 | | - } |
213 | | - // Clear the group for the next one. |
214 | | - groupLines.clear(); |
215 | | - } |
216 | | - } |
217 | | - // Add the current line to the group if it’s not empty. |
218 | | - if (!line.empty()) { |
219 | | - groupLines.push_back(line); |
220 | | - } |
221 | | - } |
222 | | - // Process any remaining group. |
223 | | - if (!groupLines.empty()) { |
224 | | - instructions.emplace_back(parseGroup(groupLines)); |
225 | | - } |
226 | | - |
227 | | - std::sort(instructions.begin(), instructions.end(), |
228 | | - [](InstructionGroup &a, InstructionGroup &b) { return a.cycleCount < b.cycleCount; }); |
| 285 | + parseInParallel(file, instructions); |
229 | 286 | // Now simulate issuing them into the ROB |
230 | 287 | for (const auto &instruction : instructions) { |
231 | 288 | bool issued = false; |
|
0 commit comments