75#define RV32_RTL_GEN_VERBOSE 0
83 const std::string& entityName)
95 bypassInstructionRegister_(
false),
96 hasForwarding_(
false),
97 variableLengthOpLatency_(
false),
99 hasCustom0Operations_(
false) {
101 for (
int i = 0; i < busNav.
count(); i++) {
120 std::cout <<
"Generated bypass logic" << std::endl;
122 std::cout <<
"Not required connectivity for bypass logic"
147 int encoding = fTemp.
encoding(name);
151 std::string encBits = bits.
toString();
162 if (name ==
"srai" || name ==
"slli" || name ==
"srli") {
177 std::string encBits = bits.
toString();
186 std::string encBits = bits.
toString();
196 std::string encBits = bits.
toString();
205 std::string encBits = bits.
toString();
214 std::string encBits = bits.
toString();
223 std::string encBits = bits.
toString();
238 const std::string opName = op.first;
244 const std::string opName = op.first;
250 const std::string opName = op.first;
251 if (op.first !=
"move") {
258 const std::string opName = op.first;
265 const std::string opName = op.first;
272 const std::string opName = op.first;
282 for (
int i = 0; i < fuNav.
count(); i++) {
297 const std::string& op)
const {
298 std::string msg =
"Cannot find operation '" + op +
"\' in machine.";
304 const BaseFUPort* port,
const std::string& type)
const {
306 std::string msg = type +
" operand port \'" + port->
name() +
307 "\' in FU \'" + fuName +
308 "\' not mapped as triggering port";
314 const BaseFUPort* port,
const std::string& type)
const {
316 std::string msg = type +
" operand port \'" + port->
name() +
317 "\' in FU \'" + fuName +
"\' not mapped as input";
323 const BaseFUPort* port,
const std::string& type)
const {
325 std::string msg = type +
" operand port \'" + port->
name() +
326 "\' in FU \'" + fuName +
"\' not mapped as output";
332 const std::string& op,
int required,
int found)
const {
333 std::string msg =
"Operation " + op +
334 " has invalid amount of operands. " +
335 std::to_string(required) +
" required, " +
336 std::to_string(found) +
" found.";
414 const int operandCount = (opName ==
"calla") ? 2 : 3;
421 if (opName !=
"calla") {
422 rdPort = op->
port(3);
427 rs1Port = op->
port(2);
428 simmPort = op->
port(1);
448 }
else if (!rs1Port->
isInput()) {
450 }
else if (!rs2Port->
isInput()) {
460 if (opName ==
"move") {
467 if (opName ==
"apc") {
468 rdPort = op->
port(2);
545 for (
int i = 0; i < rfNav.
count(); i++) {
549 if (rf->
size() > 31 && rf->
width() == 32) {
551 }
else if (rf->
size() == 16 && rf->
width() == 32) {
558 std::string msg =
"Could not find a valid register file for RISC-V";
599 std::vector<RFPort*> RFOutputPorts;
600 std::vector<RFPort*> RFInputPorts;
604 RFOutputPorts.push_back(tmpPort);
606 RFInputPorts.push_back(tmpPort);
610 assert(RFInputPorts.size() > 0);
611 assert(RFOutputPorts.size() > 1);
619 bool success =
false;
620 bool forwarding =
false;
621 for (
int l = 0; l < 2 && !success; l++) {
623 forwarding = !forwarding;
624 for (
unsigned int i = 0; i < RFOutputPorts.size() && !success; i++) {
625 std::vector<RFPort*> tmpRFOutputPorts = RFOutputPorts;
626 rs1RFPort = RFOutputPorts.at(i);
627 tmpRFOutputPorts.erase(tmpRFOutputPorts.begin() + i);
628 for (
unsigned int j = 0; j < tmpRFOutputPorts.size() && !success;
630 rs2RFPort = tmpRFOutputPorts.at(j);
631 for (
unsigned int k = 0; k < RFInputPorts.size() && !success;
633 std::vector<RFPort*> tmpRFInputPorts;
634 tmpRFInputPorts = RFInputPorts;
635 rdRFPort = RFInputPorts.at(k);
637 rs1.
port = rs1RFPort;
638 rs2.
port = rs2RFPort;
658 "Could not find enough connectivity in the "
659 "interconnect to construct RISC-V control and decode logic. Make "
661 "the minimum connections are in place and that the operand-port "
662 "bindings are valid in FUs";
678 const std::unordered_map<std::string, BaseFUPort*>& ports)
const {
679 std::set<Port*> retval;
680 for (
const auto& op : ports) {
681 retval.insert(
static_cast<Port*
>(op.second));
689 const bool& forwarding)
const {
691 rs1Ports.insert(rs1.
port);
694 rs2Ports.insert(rs2.
port);
701 rs1Ports.insert(rdPorts.begin(), rdPorts.end());
702 rs2Ports.insert(rdPorts.begin(), rdPorts.end());
705 rdPorts.insert(rd.
port);
708 for (
unsigned int i = 0; i <
busses_.size(); i++) {
709 std::vector<Bus*> tmpBusses =
busses_;
719 tmpBusses.erase(tmpBusses.begin() + i);
721 for (
unsigned int j = 0; j < tmpBusses.size(); j++) {
722 tmpBus = tmpBusses.at(j);
727 tmpBusses.erase(tmpBusses.begin() + j);
728 for (
unsigned int k = 0; k < tmpBusses.size(); k++) {
729 tmpBus = tmpBusses.at(k);
735 tmpBusses.erase(tmpBusses.begin() + k);
736 for (
unsigned int h = 0; h < tmpBusses.size(); h++) {
737 tmpBus = tmpBusses.at(h);
739 simmPorts, *tmpBus) &&
751std::unordered_map<std::string, InstructionBitVector*>
753 std::unordered_map<std::string, InstructionBitVector*> retval;
764 if (
dynamic_cast<RFPort*
>(src1)) {
765 instruction->
addMove(std::make_shared<Move>(
769 instruction->
addMove(std::make_shared<Move>(
774 if (
dynamic_cast<RFPort*
>(src2)) {
775 instruction->
addMove(std::make_shared<Move>(
779 instruction->
addMove(std::make_shared<Move>(
784 instruction->
addMove(std::make_shared<Move>(
791 retval.insert({op.first, bits});
796std::unordered_map<std::string, InstructionBitVector*>
798 std::unordered_map<std::string, InstructionBitVector*> retval;
808 if (
dynamic_cast<RFPort*
>(src1)) {
809 instruction->
addMove(std::make_shared<Move>(
813 instruction->
addMove(std::make_shared<Move>(
818 instruction->
addMove(std::make_shared<Move>(
825 retval.insert({op.first, bits});
830std::unordered_map<std::string, InstructionBitVector*>
832 std::unordered_map<std::string, InstructionBitVector*> retval;
841 if (
dynamic_cast<RFPort*
>(src1)) {
842 instruction->
addMove(std::make_shared<Move>(
846 instruction->
addMove(std::make_shared<Move>(
854 retval.insert({op.first, bits});
859std::unordered_map<std::string, InstructionBitVector*>
862 std::unordered_map<std::string, InstructionBitVector*> retval;
873 if (op.first !=
"calla") {
877 if (
dynamic_cast<RFPort*
>(src1)) {
878 instruction->
addMove(std::make_shared<Move>(
882 instruction->
addMove(std::make_shared<Move>(
887 instruction->
addMove(std::make_shared<Move>(
895 if (
dynamic_cast<RFPort*
>(src1)) {
896 instruction->
addMove(std::make_shared<Move>(
900 instruction->
addMove(std::make_shared<Move>(
905 instruction->
addMove(std::make_shared<Move>(
910 instruction->
addMove(std::make_shared<Move>(
917 retval.insert({op.first, bits});
922std::unordered_map<std::string, InstructionBitVector*>
924 std::unordered_map<std::string, InstructionBitVector*> retval;
935 if (
dynamic_cast<RFPort*
>(src1)) {
936 instruction->
addMove(std::make_shared<Move>(
940 instruction->
addMove(std::make_shared<Move>(
945 instruction->
addMove(std::make_shared<Move>(
949 if (
dynamic_cast<RFPort*
>(src2)) {
950 instruction->
addMove(std::make_shared<Move>(
954 instruction->
addMove(std::make_shared<Move>(
962 retval.insert({op.first, bits});
967std::unordered_map<std::string, InstructionBitVector*>
969 std::unordered_map<std::string, InstructionBitVector*> retval;
980 instruction->
addMove(std::make_shared<Move>(
984 if (
dynamic_cast<RFPort*
>(src1)) {
985 instruction->
addMove(std::make_shared<Move>(
989 instruction->
addMove(std::make_shared<Move>(
994 if (
dynamic_cast<RFPort*
>(src2)) {
995 instruction->
addMove(std::make_shared<Move>(
999 instruction->
addMove(std::make_shared<Move>(
1007 retval.insert({op.first, bits});
1012std::unordered_map<std::string, InstructionBitVector*>
1014 std::unordered_map<std::string, InstructionBitVector*> retval;
1020 if (op.first ==
"move") {
1025 instruction->
addMove(std::make_shared<Move>(
1029 instruction->
addMove(std::make_shared<Move>(
1033 instruction->
addMove(std::make_shared<Move>(
1038 retval.insert({
"move", bits});
1040 }
else if (op.first ==
"callr" or op.first ==
"apc") {
1043 instruction->
addMove(std::make_shared<Move>(
1049 retval.insert({op.first, bits});
1058 instruction->
addMove(std::make_shared<Move>(
1062 instruction->
addMove(std::make_shared<Move>(
1069 retval.insert({op.first, bits});
1078 std::unordered_map<std::string, InstructionBitVector*> instructions,
1079 const std::map<std::string, std::string> encodings,
1080 std::ofstream& stream)
const {
1081 assert(instructions.size() == encodings.size());
1082 for (
const auto& op : instructions) {
1083 stream <<
" elsif(fu_opcode(" << encodings.at(op.first).size()
1084 <<
" - 1 downto 0) = "
1085 <<
"\"" << encodings.at(op.first) <<
"\""
1086 <<
") then" << std::endl
1087 <<
" moves <= \"" << op.second->toString() <<
"\";"
1095 std::unordered_map<std::string, std::string> operations;
1105 stream <<
" process(fu_opcode)" << std::endl
1106 <<
" begin" << std::endl
1107 <<
" target_fu <= to_unsigned(0, " << len <<
");" << std::endl;
1110 bool firstCond =
true;
1114 for (
const auto& op : p.second) {
1125 stream << cond <<
"fu_opcode(" << iLen <<
"-1 downto 0)"
1129 <<
"\" or fu_opcode(" << uLen <<
"-1 downto 0) = \""
1135 stream << cond <<
"fu_opcode(" << iLen <<
"-1 downto 0)"
1140 int opLen = operations.at(op).size();
1141 stream << cond <<
"fu_opcode(" << opLen <<
"-1 downto 0)"
1142 <<
"= \"" << operations.at(op) <<
"\" then\n";
1144 stream <<
" target_fu <= to_unsigned(" <<
id <<
", " << len
1149 stream <<
" end if;" << std::endl <<
" end process;" << std::endl;
1151 stream << std::endl << std::endl;
1152 stream <<
" process(clk, rstx)" << std::endl
1153 <<
" begin" << std::endl
1154 <<
" if(rstx = '0') then" << std::endl
1155 <<
" target_fu_r <= (others => '0');" << std::endl
1156 <<
" elsif clk'event and clk = '1' then" << std::endl
1157 <<
" if glock_in = '0' and halt = '0' then" << std::endl
1158 <<
" target_fu_r <= target_fu;" << std::endl
1159 <<
" end if;" << std::endl
1160 <<
" end if;" << std::endl
1161 <<
" end process;" << std::endl
1168 std::map<std::string, std::string> ops,
1169 std::unordered_map<std::string, InstructionBitVector*> (
1172 std::ofstream& stream) const {
1173 if (ops.size() == 0) {
1176 bool firstOpcodeCond =
true;
1177 for (
const auto& op : ops) {
1178 std::string opcodeCond =
" elsif ";
1179 if (firstOpcodeCond) {
1180 opcodeCond =
" if ";
1181 firstOpcodeCond =
false;
1183 stream << opcodeCond <<
"fu_opcode(" << op.second.size()
1184 <<
"-1 downto 0) = \"" << op.second <<
"\"";
1185 if (rOperations_.count(op.first) && iOperations_.count(op.first)) {
1186 stream <<
" or fu_opcode(" << iOperations_.at(op.first).size()
1187 <<
"-1 downto 0) = \"" << iOperations_.at(op.first)
1191 bool firstTargetCond =
true;
1192 for (
const auto& p : sourceOperationMap_) {
1193 std::string targetCond =
" elsif ";
1194 if (firstTargetCond) {
1195 targetCond =
" if ";
1196 firstTargetCond =
false;
1198 stream << targetCond +
"target_fu_r = "
1199 << sourcePortID_.at(p.first) <<
" then \n";
1200 std::unordered_map<std::string, InstructionBitVector*>
1201 instructions = (this->*instructionFunc)(p.first, rs2RFPort_);
1202 std::string bits = instructions.at(op.first)->toString();
1203 reverse(bits.begin(), bits.end());
1204 bits = bits.substr(rs1BusStart_, rs1BusWidth_);
1205 reverse(bits.begin(), bits.end());
1206 stream <<
" moves(rs1_start_c + rs1_width_c -1 downto"
1208 <<
" <= \"" << bits <<
"\";\n";
1209 for (
const auto& val : instructions) {
1213 stream <<
" end if;" << std::endl;
1215 stream <<
" end if;" << std::endl;
1219RV32MicroCodeGenerator::addRs2ForwardingConditions(
1220 std::map<std::string, std::string> ops,
1221 std::unordered_map<std::string, InstructionBitVector*> (
1224 std::ofstream& stream) const {
1225 bool firstOpcodeCond = true;
1226 for (
const auto& op : ops) {
1227 std::string opcodeCond =
" elsif ";
1228 if (firstOpcodeCond) {
1229 opcodeCond =
" if ";
1230 firstOpcodeCond =
false;
1232 stream << opcodeCond <<
"fu_opcode(" << op.second.size()
1233 <<
"-1 downto 0) = \"" << op.second <<
"\" then\n";
1234 bool firstTargetCond =
true;
1235 for (
const auto& p : sourceOperationMap_) {
1236 std::string targetCond =
" elsif ";
1237 if (firstTargetCond) {
1238 targetCond =
" if ";
1239 firstTargetCond =
false;
1241 stream << targetCond +
"target_fu_r = "
1242 << sourcePortID_.at(p.first) <<
" then \n";
1243 std::unordered_map<std::string, InstructionBitVector*>
1244 instructions = (this->*instructionFunc)(rs1RFPort_, p.first);
1245 std::string bits = instructions.at(op.first)->toString();
1246 reverse(bits.begin(), bits.end());
1247 bits = bits.substr(rs2BusStart_, rs2BusWidth_);
1248 reverse(bits.begin(), bits.end());
1249 stream <<
" moves(rs2_start_c + rs2_width_c -1 downto"
1251 <<
" <= \"" << bits <<
"\";\n";
1252 for (
const auto& val : instructions) {
1256 stream <<
" end if;" << std::endl;
1258 stream <<
" end if;" << std::endl;
1262RV32MicroCodeGenerator::generateMap(
const std::string& dstDirectory) {
1269 std::string mapFile = dstDirectory +
DS +
"rv32_microcode.vhdl";
1271 std::ofstream stream;
1272 stream.open(mapFile);
1275 stream <<
"library IEEE;" << std::endl
1276 <<
"use IEEE.std_logic_1164.all;" << std::endl
1277 <<
"use IEEE.numeric_std.all;" << std::endl
1278 <<
"use work." << entityName_ <<
"_globals.all;" << std::endl
1282 stream <<
"entity rv32_microcode is" << std::endl <<
"port(" << std::endl;
1283 if (hasForwarding_) {
1284 stream <<
" clk : in std_logic;" << std::endl
1285 <<
" rstx : in std_logic;" << std::endl
1286 <<
" glock_in : in std_logic;" << std::endl
1287 <<
" data_hazard_in : in std_logic;" << std::endl
1288 <<
" rs1_hazard_in : in std_logic;" << std::endl
1289 <<
" rs2_hazard_in : in std_logic;" << std::endl
1290 <<
" halt : in std_logic;" << std::endl;
1292 stream <<
" fu_opcode_in : in std_logic_vector(16 downto 0);"
1294 <<
" moves_out : out std_logic_vector(INSTRUCTIONWIDTH-1 "
1298 <<
"end rv32_microcode;" << std::endl
1300 <<
"architecture rtl of rv32_microcode is" << std::endl
1301 <<
" signal fu_opcode : std_logic_vector(16 downto 0);"
1303 <<
" signal moves : std_logic_vector(INSTRUCTIONWIDTH-1 "
1306 <<
" constant rs1_start_c : integer := " << rs1BusStart_ <<
";"
1308 <<
" constant rs2_start_c : integer := " << rs2BusStart_ <<
";"
1310 <<
" constant rs1_width_c : integer := " << rs1BusWidth_ <<
";"
1312 <<
" constant rs2_width_c : integer := " << rs2BusWidth_ <<
";"
1314 if (hasForwarding_) {
1315 int len = std::ceil(std::log2(sourceOperationMap_.size()));
1316 stream <<
" signal target_fu : unsigned(" << len <<
"-1 downto 0);"
1318 stream <<
" signal target_fu_r : unsigned (" << len
1319 <<
"-1 downto 0);" << std::endl
1320 <<
" signal data_hazard : std_logic;\n"
1321 <<
" signal rs1_hazard : std_logic;\n"
1322 <<
" signal rs2_hazard : std_logic;\n";
1326 <<
" begin" << std::endl
1328 <<
" fu_opcode <= fu_opcode_in;" << std::endl
1329 <<
" moves_out <= moves;" << std::endl
1331 if (hasForwarding_) {
1332 stream <<
" data_hazard <= data_hazard_in;" << std::endl
1333 <<
" rs1_hazard <= rs1_hazard_in;" << std::endl
1334 <<
" rs2_hazard <= rs2_hazard_in;" << std::endl;
1335 stream << std::endl;
1336 generateFUTargetProcess(stream);
1338 stream <<
" process(fu_opcode";
1339 if (hasForwarding_) {
1340 stream <<
", data_hazard, rs1_hazard, rs2_hazard, target_fu_r";
1342 stream <<
")" << std::endl;
1343 stream <<
" begin" << std::endl;
1345 std::unordered_map<std::string, InstructionBitVector*> instructions =
1346 constructRInstructions(rs1RFPort_, rs2RFPort_);
1347 bool firstCond =
true;
1348 for (
const auto& op : instructions) {
1350 stream <<
" if(fu_opcode = \"" << rOperations_.at(op.first)
1351 <<
"\") then" << std::endl
1352 <<
" moves <= \"" << op.second->toString() <<
"\";"
1358 stream <<
" elsif(fu_opcode(" << rOperations_.at(op.first).size()
1359 <<
" - 1 downto 0) = \"" << rOperations_.at(op.first) <<
"\""
1360 <<
") then" << std::endl
1361 <<
" moves <= \"" << op.second->toString() <<
"\";"
1366 instructions = constructIInstructions(rs1RFPort_, rs1RFPort_);
1367 addBitsToMap(instructions, iOperations_, stream);
1369 instructions = constructSInstructions(rs1RFPort_, rs2RFPort_);
1370 addBitsToMap(instructions, sOperations_, stream);
1372 instructions = constructBInstructions(rs1RFPort_, rs2RFPort_);
1373 addBitsToMap(instructions, bOperations_, stream);
1375 instructions = constructUJInstructions();
1376 addBitsToMap(instructions, ujOperations_, stream);
1378 instructions = constructR1RInstructions(rs1RFPort_, rs2RFPort_);
1379 addBitsToMap(instructions, r1rOperations_, stream);
1381 instructions = constructR1Instructions(rs1RFPort_, rs2RFPort_);
1382 addBitsToMap(instructions, r1Operations_, stream);
1384 stream <<
" else" << std::endl;
1385 stream <<
" moves <= \"" + NOP_ +
"\";" << std::endl;
1387 stream <<
" end if;" << std::endl;
1389 if (hasForwarding_) {
1390 stream <<
" if(data_hazard = '1') then\n"
1391 <<
" if(rs1_hazard = '1') then\n";
1392 addRs1ForwardingConditions(
1395 addRs1ForwardingConditions(
1398 addRs1ForwardingConditions(
1401 addRs1ForwardingConditions(
1404 addRs1ForwardingConditions(
1407 addRs1ForwardingConditions(
1410 stream <<
" end if;\n"
1411 <<
" if(rs2_hazard = '1') then\n";
1412 addRs2ForwardingConditions(
1415 addRs2ForwardingConditions(
1418 addRs2ForwardingConditions(
1421 stream <<
" end if;\n"
1425 stream <<
" end process;" << std::endl;
1427 stream <<
"end architecture rtl;" << std::endl;
1433RV32MicroCodeGenerator::generateOperationLatencyLogic(
1435 std::map<std::string, std::string> operations;
1436 operations.insert(rOperations_.begin(), rOperations_.end());
1437 operations.insert(r1rOperations_.begin(), r1rOperations_.end());
1439 for (
const auto& op : iOperations_) {
1440 if (!rOperations_.count(op.first)) {
1441 operations.insert(op);
1444 std::map<std::string, int> opLatency;
1445 for (
const auto& op : operations) {
1448 if (operation->
latency() > 1) {
1449 opLatency.insert({op.first, operation->
latency() - 1});
1450 if (operation->
latency() > maxVal) {
1451 maxVal = operation->
latency();
1455 int len = std::ceil(std::log2((maxVal)) + 1);
1457 if (opLatency.size() == 0) {
1458 return "op_latency <= to_unsigned(0,op_lat_width_c);";
1460 variableLengthOpLatency_ =
true;
1462 "process(fu_opcode)\n"
1464 bool firstCond =
true;
1465 for (
const auto& op : opLatency) {
1466 std::string cond =
" elsif ";
1471 if (rOperations_.count(op.first) && iOperations_.count(op.first)) {
1472 cond +=
"fu_opcode = \"" + rOperations_.at(op.first) +
"\" or " +
1474 std::to_string(iOperations_.at(op.first).size()) +
1475 "-1 downto 0) = \"" + iOperations_.at(op.first) +
1478 cond +=
"fu_opcode(" +
1479 std::to_string(operations.at(op.first).size()) +
1480 "-1 downto 0) = \"" + operations.at(op.first) +
1483 logic += cond +
" op_latency <= to_unsigned(" +
1484 std::to_string(op.second) +
",op_lat_width_c);\n";
1488 " op_latency <= to_unsigned(0,op_lat_width_c);\n"
1495RV32MicroCodeGenerator::generateWrapper(
1498 "rs1-bus-width", std::to_string(rs1BusWidth_));
1500 "rs2-bus-width", std::to_string(rs2BusWidth_));
1502 "rd-bus-width", std::to_string(rdBusWidth_));
1504 "simm-bus-width", std::to_string(simmBusWidth_));
1507 "rs1-bus-start", std::to_string(rs1BusStart_));
1509 "rs2-bus-start", std::to_string(rs2BusStart_));
1511 "rd-bus-start", std::to_string(rdBusStart_));
1513 "simm-bus-start", std::to_string(simmBusStart_));
1516 "rs1-rf-start", std::to_string(rs1RFStart_));
1518 "rs2-rf-start", std::to_string(rs2RFStart_));
1520 "rd-rf-start", std::to_string(rdRFStart_));
1522 "simm-rf-start", std::to_string(simmRFStart_));
1530 std::string nop = NOP_;
1531 reverse(nop.begin(), nop.end());
1532 nop = nop.substr(rdBusStart_, rdBusWidth_);
1533 reverse(nop.begin(), nop.end());
1534 const std::string rdNOP = nop;
1539 "rv32-microcode-simm-assign",
"simm_out <= simm_r;");
1545 "rv32-microcode-instruction-assign",
1546 "instruction <= instruction_in;");
1548 if (hasForwarding_) {
1549 std::string forwardingPorts =
1550 " clk : in std_logic;\n"
1551 " rstx : in std_logic;\n"
1552 " glock_in : in std_logic;\n"
1553 " data_hazard_in : in std_logic;\n"
1554 " rs1_hazard_in : in std_logic;\n"
1555 " rs2_hazard_in : in std_logic;\n"
1556 " halt : in std_logic;\n";
1558 std::string forwardingPortMapping =
1561 "glock_in => glock_in,\n"
1562 "data_hazard_in => data_hazard,\n"
1563 "rs1_hazard_in => rs1_hazard,\n"
1564 "rs2_hazard_in => rs2_hazard,\n"
1565 "halt => filling_instruction_pipeline,";
1569 "forwarding-port-mapping", forwardingPortMapping);
1572 "data-hazard-stall",
"and data_hazard = '0'");
1574 "data-hazard-assign-conds",
1575 "elsif(data_hazard_r = '1') then\n"
1576 " data_hazard <= '0';");
1578 "data-hazard-detection-sensitivity-list-signals",
1582 "rv32-microcode-op-latency-process",
1583 generateOperationLatencyLogic(instantiator));
1584 std::string otherStates;
1586 if (variableLengthOpLatency_) {
1587 otherStates +=
",HANDLE_OP_LATENCY";
1589 if (!bypassInstructionRegister_) {
1590 otherStates +=
",FILL_INSTRUCTION_PIPELINE_2";
1593 "rv32-microcode-other-states", otherStates);
1594 std::string executeLogic;
1595 std::string fsm_sensitivity_list_signals;
1597 " if(glock_in = '1') then\n"
1599 " stall_ifetch <= '0';\n"
1601 " elsif (rv_jump_wire = '1' or rv_auipc_wire = '1') then\n"
1602 " rd_bus_move <= rd_move;\n"
1603 " stall_ifetch <= '0';\n"
1605 " if rv_auipc_wire = '0' then\n"
1606 " NS <= FILL_INSTRUCTION_PIPELINE;\n"
1608 if (!hasForwarding_) {
1609 fsm_sensitivity_list_signals =
", data_hazard";
1610 if (variableLengthOpLatency_) {
1612 " elsif(op_latency_stall = '1' and data_hazard = '0') then\n"
1614 " NS <= HANDLE_OP_LATENCY;\n"
1615 " stall_ifetch <= '1';\n"
1616 " rd_bus_move <= rd_nop_c;\n";
1619 " elsif(data_hazard = '1') then\n"
1621 " rd_bus_move <= rd_nop_c;\n"
1622 " stall_ifetch <= '1';\n"
1624 " elsif (is_control_flow_op = '1') then\n"
1626 " stall_ifetch <= '1';\n"
1627 " NS <= HANDLE_CONTROL_FLOW_OP;\n"
1628 " handle_control_flow_ns <= '1';\n"
1631 " stall_ifetch <= '0';\n"
1635 if (variableLengthOpLatency_) {
1637 " elsif(op_latency_stall = '1') then\n"
1639 " NS <= HANDLE_OP_LATENCY;\n"
1640 " stall_ifetch <= '1';\n"
1641 " rd_bus_move <= rd_nop_c;\n";
1644 " elsif (is_control_flow_op = '1') then\n"
1646 " stall_ifetch <= '1';\n"
1647 " NS <= HANDLE_CONTROL_FLOW_OP;\n"
1648 " handle_control_flow_ns <= '1';\n"
1651 " stall_ifetch <= '0';\n"
1655 if (variableLengthOpLatency_) {
1656 fsm_sensitivity_list_signals +=
", op_latency_stall";
1659 "when HANDLE_OP_LATENCY =>\n"
1661 " stall_ifetch <= '1';\n"
1662 " rd_bus_move <= rd_nop_c;\n"
1663 " NS <= HANDLE_OP_LATENCY;\n"
1664 " if(op_latency_stall = '0') then\n"
1666 " stall_ifetch <= '0';\n"
1667 " rd_bus_move <= rd_move;\n"
1670 std::string instructionPipelineStates;
1671 if (bypassInstructionRegister_) {
1672 instructionPipelineStates =
1673 "when FILL_INSTRUCTION_PIPELINE =>\n"
1674 " filling_instruction_pipeline <= '1';\n"
1676 " rd_bus_move <= rd_nop_c;\n"
1677 " stall_ifetch <= '0';\n"
1678 " NS <= EXECUTE;\n";
1680 instructionPipelineStates =
1681 "when FILL_INSTRUCTION_PIPELINE =>\n"
1682 " filling_instruction_pipeline <= '1';\n"
1684 " rd_bus_move <= rd_nop_c;\n"
1685 " stall_ifetch <= '0';\n"
1686 " NS <= FILL_INSTRUCTION_PIPELINE_2;\n"
1689 "when FILL_INSTRUCTION_PIPELINE_2 =>\n"
1690 " filling_instruction_pipeline <= '1';\n"
1692 " rd_bus_move <= rd_nop_c;\n"
1693 " stall_ifetch <= '0';\n"
1698 "rv32-microcode-instruction-pipeline-logic",
1699 instructionPipelineStates);
1702 "rv32-microcode-fsm-sensitivity-list-signals",
1703 fsm_sensitivity_list_signals);
1705 "rv32-microcode-execute-logic", executeLogic);
1707 if (hasCustom0Operations_) {
1709 "or frame_r_c(1) = opcode");
1712 templateDir +
DS +
"rv32_microcode_wrapper.vhdl.tmpl",
1713 fileDst +
DS +
"rv32_microcode_wrapper.vhdl");
1717RV32MicroCodeGenerator::generateRTL(
1719 generateMap(fileDst);
1720 generateWrapper(instantiator, fileDst);
1724RV32MicroCodeGenerator::setBypassInstructionRegister(
const bool& value) {
1725 bypassInstructionRegister_ = value;
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
find Finds info of the inner loops in the false
#define RV32_RTL_GEN_VERBOSE
int instructionFormatCount() const
int moveSlotCount() const
MoveSlot & moveSlot(int index) const
InstructionFormat & instructionFormat(int index) const
void pushBack(long long unsigned int integer, int size)
std::string toString() const
InstructionBitVector * bemInstructionBits(const TTAProgram::Instruction &)
static std::string dataDirPath(const std::string &prog)
static const std::string DIRECTORY_SEPARATOR
void instantiateTemplateFile(const std::string &templateFile, const std::string &dstFile)
void replacePlaceholder(const std::string &key, const std::string &replacer, bool append=false)
static std::string generateMITLicense(const std::string &year, const std::string &comment)
static bool isConnected(const TTAMachine::Port &sourcePort, const TTAMachine::Port &destinationPort, const TTAMachine::Guard *guard=NULL)
DestinationField & destinationField() const
virtual int width() const
bool hasDestinationField() const
const BinaryEncoding * bem_
std::vector< Bus * > busses_
void findOperationSources()
std::unordered_map< std::string, InstructionBitVector * > constructIInstructions(Port *src1, Port *src2) const
void addR1RPorts(const std::string &opName)
void addRs1ForwardingConditions(std::map< std::string, std::string > ops, std::unordered_map< std::string, InstructionBitVector * >(ProGe::RV32MicroCodeGenerator::*instructionFunc)(Port *p1, Port *p2) const, std::ofstream &stream) const
std::unordered_map< std::string, BaseFUPort * > rs1Ports_
FunctionUnit * mapFunctionUnit(const std::string &operation) const
bool findConnectedBusses(Connection &rs1, Connection &rs2, Connection &rd, Connection &simm, const bool &forwarding) const
std::unordered_map< std::string, BaseFUPort * > simmPorts_
RV32MicroCodeGenerator(const Machine &machine, const BinaryEncoding &bem, const std::string &entityName)
std::unordered_map< std::string, BaseFUPort * > rdPorts_
std::map< std::string, std::string > r1rOperations_
ProgramImageGenerator * pig_
void throwOutputPortError(const BaseFUPort *port, const std::string &type) const
void validateOperations() const
void addR1Ports(const std::string &opName)
std::map< std::string, std::string > r1Operations_
void addBitsToMap(std::unordered_map< std::string, InstructionBitVector * > instructions, const std::map< std::string, std::string > encodings, std::ofstream &stream) const
std::unordered_map< std::string, InstructionBitVector * > constructR1Instructions(Port *src1, Port *src2) const
void addRPorts(const std::string &opName)
void addSPorts(const std::string &opName)
void addUJPorts(const std::string &opName)
std::map< std::string, std::string > iOperations_
std::map< std::string, std::string > bOperations_
bool hasCustom0Operations_
std::unordered_map< std::string, InstructionBitVector * > constructRInstructions(Port *src1, Port *src2) const
std::map< std::string, std::string > rOperations_
~RV32MicroCodeGenerator()
void throwOperationNotFoundError(const std::string &op) const
std::unordered_map< std::string, InstructionBitVector * > constructSInstructions(Port *src1, Port *src2) const
void generateFUTargetProcess(std::ofstream &stream)
std::map< std::string, std::string > sOperations_
std::unordered_map< std::string, BaseFUPort * > rs2Ports_
std::unordered_map< Port *, std::vector< std::string > > sourceOperationMap_
void throwTriggeringPortError(const BaseFUPort *port, const std::string &type) const
std::map< std::string, std::string > ujOperations_
std::unordered_map< std::string, InstructionBitVector * > constructR1RInstructions(Port *src1, Port *src2) const
void initializeOperations()
void addIPorts(const std::string &opName)
std::unordered_map< Port *, int > sourcePortID_
void throwOperandCountError(const std::string &op, int required, int found) const
std::unordered_map< std::string, InstructionBitVector * > constructUJInstructions() const
std::set< Port * > operationPorts(const std::unordered_map< std::string, BaseFUPort * > &ports) const
void findOperationPorts()
std::unordered_map< std::string, InstructionBitVector * > constructBInstructions(Port *src1, Port *src2) const
void throwInputPortError(const BaseFUPort *port, const std::string &type) const
void addBPorts(const std::string &opName)
void loadMachine(const TTAMachine::Machine &machine)
CodeCompressorPlugin & compressor()
void loadBEM(const BinaryEncoding &bem)
virtual int width() const
FunctionUnit * parentUnit() const
virtual int width() const
virtual RFPort * port(const std::string &name) const
int immediateWidth() const
virtual TCEString name() const
SpecialRegisterPort * returnAddressPort() const
virtual bool isTriggering() const
virtual HWOperation * operation(const std::string &name) const
virtual bool hasOperation(const std::string &name) const
virtual FUPort * port(int operand) const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
virtual FunctionUnitNavigator functionUnitNavigator() const
bool hasOperation(const TCEString &opName) const
virtual BusNavigator busNavigator() const
virtual ControlUnit * controlUnit() const
virtual Socket * outputSocket() const
virtual bool isInput() const
virtual bool isOutput() const
virtual Socket * inputSocket() const
virtual std::string name() const
virtual bool zeroRegister() const
virtual int portCount() const
virtual int inputPortCount(bool countBidir=false) const
virtual int outputPortCount(bool countBidir=false) const
void addMove(std::shared_ptr< Move > move)
const std::string RISCV_S_TYPE_NAME
const std::string RISCV_R1R_TYPE_NAME
const std::string RISCV_B_TYPE_NAME
const std::string RISCV_J_TYPE_NAME
const std::string RISCV_R_TYPE_NAME
const std::string RISCV_R1_TYPE_NAME
const std::string RISCV_I_TYPE_NAME
const std::string RISCV_U_TYPE_NAME
const std::vector< std::string > RISCVMExtensionOperations
const std::map< std::string, std::string > RISCVOperationNameTable