45 #include "boost/regex.hpp"
46 #include "boost/format.hpp"
134 const std::string& name) :
180 delay = sourceDelay + busDelay + destinationDelay;
182 #ifdef DEBUG_DELAY_ESTIMATION
185 <<
"," << path.
bus().
name() <<
","
187 <<
"delays={" << sourceDelay <<
"," << busDelay <<
","
188 << destinationDelay <<
"} = " << delay << std::endl;
229 std::string socketName =
"";
237 for (
int i = 0; i < socketNav.
count(); ++i) {
241 socketName =
"input_sub_socket";
243 socketName =
"output_sub_socket";
251 socketParameters(socket);
253 FanInFanOutCombinationSet::const_iterator iter =
254 parameterSet.begin();
255 std::string socketNameCopy = socketName;
256 for (; iter != parameterSet.end(); iter++) {
257 socketName = socketNameCopy +
" " +
264 area += valueFromKeyValuePairString(
267 std::set<std::string>::iterator iter =
268 missingComponents_.find(
"area" + socketName);
269 if (iter == missingComponents_.end()) {
270 std::cerr <<
"Warning: Could not get area data "
272 << socketName <<
"' from HDB: "
273 << hdb.
fileName() <<
". Area of this "
274 <<
"socket not counted to total."
276 missingComponents_.insert(
"area" + socketName);
285 std::string(
"Could not get socket area data '") +
286 socketName +
"' from HDB: " + hdb.
fileName() +
291 std::string busName =
"";
299 for (
int i = 0; i < busNav.
count(); ++i) {
304 FanInFanOutCombinationSet::const_iterator iter =
305 parameterSet.begin();
306 for (; iter != parameterSet.end(); iter++) {
307 busName =
"sub_bus " +
314 area += valueFromKeyValuePairString(
317 std::set<std::string>::iterator iter =
318 missingComponents_.find(
"area" + busName);
319 if (iter == missingComponents_.end()) {
320 std::cerr <<
"Warning: Could not get area data "
322 << busName <<
"' from HDB: "
323 << hdb.
fileName() <<
". Area of this "
324 <<
"bus not counted to total."
326 missingComponents_.insert(
"area" + busName);
335 std::string(
"Could not get bus area data '") +
336 busName +
"' from HDB. " + hdb.
fileName() +
365 std::string socketName =
"";
371 for (
int i = 0; i < socketNav.
count(); ++i) {
375 socketName =
"input_sub_socket";
377 socketName =
"output_sub_socket";
385 socketParameters(socket);
387 FanInFanOutCombinationSet::const_iterator iter =
388 parameterSet.begin();
389 std::string socketNameCopy = socketName;
390 for (; iter != parameterSet.end(); iter++) {
391 socketName = socketNameCopy +
" " +
402 valueFromKeyValuePairString(
406 valueFromKeyValuePairString(
414 activeEnergy*activeCycles;
419 idleEnergy*idleCycles;
422 totalIdleEnergy + totalActiveEnergy;
423 energy += totalEnergy;
424 #ifdef DEBUG_ENERGY_ESTIMATION
426 <<
"socket " << socket.
name() <<
", subsocket "
427 << socketName <<
": "
428 <<
"active energy = " << activeEnergy
429 <<
" mJ/cycle * " << activeCycles <<
" cycle = "
430 << totalActiveEnergy <<
", "
431 <<
"idle energy = " << idleEnergy
432 <<
" mJ/cycle * " << idleCycles <<
" cycle = "
433 << totalIdleEnergy <<
" TOTAL = " << totalEnergy
440 std::string(
"Could not get socket area data '") +
444 std::string busName =
"";
449 for (
int i = 0; i < busNav.
count(); ++i) {
454 FanInFanOutCombinationSet::const_iterator iter =
455 parameterSet.begin();
456 for (; iter != parameterSet.end(); iter++) {
457 busName =
"sub_bus " +
468 valueFromKeyValuePairString(
472 valueFromKeyValuePairString(
480 activeEnergy*activeCycles;
485 idleEnergy*idleCycles;
488 totalIdleEnergy + totalActiveEnergy;
489 energy += totalEnergy;
490 #ifdef DEBUG_ENERGY_ESTIMATION
492 <<
"bus " << bus.
name() <<
", subbus "
494 <<
"active energy = " << activeEnergy
495 <<
" mJ/cycle * " << activeCycles <<
" cycle = "
496 << totalActiveEnergy <<
", "
497 <<
"idle energy = " << idleEnergy
498 <<
" mJ/cycle * " << idleCycles <<
" cycle = "
499 << totalIdleEnergy <<
" TOTAL = " << totalEnergy
506 std::string(
"Could not get bus energy data '") + busName +
524 std::string socketName =
"";
527 socketName =
"input_sub_socket";
529 socketName =
"output_sub_socket";
536 socketParameters(socket);
538 FanInFanOutCombinationSet::const_iterator iter =
539 parameterSet.begin();
540 std::string socketNameCopy = socketName;
541 for (; iter != parameterSet.end(); iter++) {
542 socketName = socketNameCopy +
" " +
547 (*iter).fanIn == 1 && (*iter).fanOut == 1) {
554 delay += valueFromKeyValuePairString(
558 std::set<std::string>::iterator iter =
559 missingComponents_.find(
"tdelay" + socketName);
560 if (iter == missingComponents_.end()) {
561 std::cerr <<
"Warning: Could not get throughput delay "
563 << socketName <<
"' from HDB: "
564 << hdb.
fileName() <<
". This value is "
565 <<
"not counted to total." << std::endl;
566 missingComponents_.insert(
"tdelay" + socketName);
573 std::string(
"Cannot fetch socket delay data '") +
585 std::string busName =
"";
589 FanInFanOutCombinationSet::const_iterator iter =
590 parameterSet.begin();
591 for (; iter != parameterSet.end(); iter++) {
592 busName =
"sub_bus " +
601 delay += valueFromKeyValuePairString(
605 std::set<std::string>::iterator iter =
606 missingComponents_.find(
"tdelay" + busName);
607 if (iter == missingComponents_.end()) {
608 std::cerr <<
"Warning: Could not get throughput delay "
610 << busName <<
"' from HDB: "
611 << hdb.
fileName() <<
". This value is "
612 <<
"not counted to total." << std::endl;
613 missingComponents_.insert(
"tdelay" + busName);
620 std::string(
"Cannot fetch bus delay data '") +
642 std::string entry =
"delay_subsocket_reference";
652 return valueFromKeyValuePairString(
657 std::string(
"Cannot fetch socket delay data '") +
678 "throughput_delay", implementationId, name_).
doubleValue();
683 std::string(
"Cannot fetch bus delay data. ") +
702 const std::string& keyName,
const std::string& keyValuePairString) {
703 boost::smatch parsed;
705 (boost::format(
"(.*)(%s)=([^\\s]*)(.*)") % keyName).str());
706 if (!regex_match(keyValuePairString, parsed, regexp)) {
709 "Key not found in value string.");
711 if (parsed.size() < 3)
737 std::vector<std::size_t>& inputWidths,
738 std::vector<std::size_t>& outputWidths) {
740 std::sort(inputWidths.begin(), inputWidths.end());
741 std::sort(outputWidths.begin(), outputWidths.end());
743 std::set<std::size_t> allWidthsTemp;
745 inputWidths.begin(), inputWidths.end(),
746 std::insert_iterator<std::set<std::size_t> >(
747 allWidthsTemp, allWidthsTemp.begin()));
749 outputWidths.begin(), outputWidths.end(),
750 std::insert_iterator<std::set<std::size_t> >(
751 allWidthsTemp, allWidthsTemp.begin()));
752 std::vector<std::size_t> allWidths;
754 allWidthsTemp.begin(), allWidthsTemp.end(),
755 std::insert_iterator<std::vector<std::size_t> >(
756 allWidths, allWidths.begin()));
760 for (std::vector<std::size_t>::iterator i = allWidths.begin();
761 i != allWidths.end(); ++i) {
763 const unsigned int width = *i;
766 std::size_t fanIn = 0;
767 for (
unsigned int n = 0; n < inputWidths.size(); n++) {
769 if (width > inputWidths.at(n) && inputWidths.at(n) > 0)
771 if (inputWidths.at(n) != 0) {
777 std::size_t fanOut = 0;
778 for (
unsigned int n = 0; n < outputWidths.size(); n++) {
780 if (width > outputWidths.at(n) && outputWidths.at(n) > 0)
782 if (outputWidths.at(n) != 0) {
787 if (fanIn == 0 || fanOut == 0)
790 parameters.
fanIn = fanIn;
791 parameters.
fanOut = fanOut;
793 combinations.push_back(parameters);
795 for (
unsigned int n = 0; n < inputWidths.size(); n++) {
796 if (inputWidths.at(n) > width) {
797 inputWidths.at(n) = inputWidths.at(n) - width;
799 inputWidths.at(n) = 0;
802 for (
unsigned int n = 0; n < outputWidths.size(); n++) {
803 if (outputWidths.at(n) > width) {
804 outputWidths.at(n) = outputWidths.at(n) - width;
806 outputWidths.at(n) = 0;
810 for (
unsigned int n = 0; n < allWidths.size(); n++) {
811 if (allWidths.at(n) > width) {
812 allWidths.at(n) = allWidths.at(n) - width;
830 FanInFanOutCombinationSet
834 std::vector<std::size_t> inputWidths;
835 std::vector<std::size_t> outputWidths;
841 for (
int i = 0; i < socket.
portCount(); i++) {
842 outputWidths.push_back(socket.
port(i)->
width());
848 for (
int i = 0; i < socket.
portCount(); i++) {
849 inputWidths.push_back(socket.
port(i)->
width());
852 return generateFanInFanOutCombinations(inputWidths, outputWidths);
861 FanInFanOutCombinationSet
865 std::vector<std::size_t> inputWidths;
866 std::vector<std::size_t> outputWidths;
870 for (
int i = 0; i < socketNav.
count(); ++i) {
873 std::size_t width = 0;
874 for (
int port = 0; port < socket.
portCount(); port++) {
875 if (
static_cast<unsigned int>(
884 inputWidths.push_back(width);
886 outputWidths.push_back(width);
891 return generateFanInFanOutCombinations(inputWidths, outputWidths);
899 using namespace ProGe;
918 "Generates the IC as as an AND-OR network.";
936 decoderGenerator_(NULL),
941 "Generates wires to the internal hardware debugger if "
943 +
"', and to the external debugger if the value is '"
945 "for softreset and break, are added if the value is '"
949 "Generates code that prints bus trace if the value is '" +
953 "The first cycle for which the bus trace is printed.");
956 "Generates code that prints global lock trace if the value is"
961 "The first cycle for which the global lock trace is printed. "
966 "-1 delay slot by removing instruction fetch register. "
977 delete decoderGenerator_;
993 icGenerator_->addICToNetlist(generator, netlistBlock);
996 decoderGenerator_->completeDecoderBlock(generator, netlistBlock);
998 if (ttamachine_.isRISCVMachine()) {
999 addRV32MicroCode(netlistBlock, generator);
1015 "rv32_microcode_wrapper",
"rv32_microcode_wrapper_i");
1049 "instruction_in",
"IMEMWIDTHINMAUS*IMEMMAUWIDTH",
BIT_VECTOR,
1052 netlist.
connect(*microCodeImmOut, *decoderRISCVSimmPort);
1094 netlist.
connect(*rvJumpPortMicroCode, *rvJumpPortIfetch);
1095 netlist.
connect(*rvAuipcPortMicroCode, *rvAuipcPortIfetch);
1096 netlist.
connect(*rvOffsetPortMicroCode, *rvOffsetPortIfetch);
1098 netlist.
connect(*ifetchStallPortMicroCode, *ifetchStallPortIFetch);
1103 generateDebugger() &&
1104 "Entered debugger connection generation without cause.");
1113 bool is_external =
false, is_internal =
false, is_minimal =
false;
1125 for (std::size_t i = 0; i < toplevelBlock.
subBlockCount(); i++) {
1126 icBlock = &toplevelBlock.
subBlock(i);
1148 if (is_minimal || is_external) {
1156 decoderBlock->
port(
"lock_req");
1157 int bit = decoderGenerator_->glockRequestWidth()-1;
1159 *dbGlockReqPort, *decoderGlockReqPort, 0, bit, 1);
1165 *ifetchDebugResetPort);
1170 *ifetchDebugLockRqPort);
1176 *ifetchCyclecountPort, *ttaCyclecountPort);
1181 *ifetchLockcountPort, *ttaLockcountPort);
1199 *icBustracePort, *ttaBustracePort);
1203 "db_pc_next",
"IMEMADDRWIDTH",
1217 }
else if (is_internal) {
1219 "db_bp_ena",
"1+db_breakpoints",
1222 "bp_target_cc",
"db_breakpoints_cc*db_data_width",
1225 "bp_target_pc",
"db_breakpoints_pc*IMEMADDRWIDTH",
1229 "db_bp_hit",
"2+db_breakpoints",
1232 "db_tta_continue",
"1",
BIT,
ProGe::IN, toplevelBlock);
1234 "db_tta_forcebreak",
"1",
BIT,
ProGe::IN, toplevelBlock);
1236 "db_tta_stdoutbreak",
"1",
BIT,
ProGe::IN, toplevelBlock);
1242 dbsmBlock->setParameter(
"cyclecnt_width_g",
"integer",
1244 dbsmBlock->setParameter(
"pc_width_g",
"integer",
1250 *dbsmClkPort, generator.
clkPort(toplevelBlock));
1255 *dbsmNresetPort, generator.
rstPort(toplevelBlock));
1258 "bp_ena",
"1+db_breakpoints",
1263 "bp_target_cc",
"db_breakpoints_cc*cyclecnt_width_g",
1273 "bp_target_pc",
"db_breakpoints_pc*IMEMADDRWIDTH",
1284 *ttaContinuePort, *dbsmContinuePort);
1289 *dbsmForceBreakPort);
1294 *ttaStdoutBreakPort, *dbsmStdoutBreakPort);
1297 "bp_hit",
"2+db_breakpoints",
1304 *toplevelBlock.
port(
"busy"), *dbsmExtlockPort);
1312 decoderBlock->
port(
"lock_req");
1313 int bit = decoderGenerator_->glockRequestWidth()-1;
1315 *dbsmGlockReqPort, *decoderGlockReqPort, 0, bit, 1);
1321 *ifetchDebugLockRqPort);
1325 *ifetchDebugResetPort);
1339 *ifetchPCNextPort, *dbsmPCNextPort);
1344 *ifetchCyclecountPort, *ttaCyclecountPort);
1346 *ifetchCyclecountPort, *dbsmCyclecountPort);
1351 *ifetchLockcountPort, *ttaLockcountPort);
1353 "db_instr",
"IMEMWIDTHINMAUS*IMEMMAUWIDTH",
1356 fetchBlock->
port(
"fetchblock");
1358 *ifetchFetchblockPort, *ttaInstrPort);
1364 NetlistPort* decoderDBResetPort = decoderBlock->
port(
"db_tta_nreset");
1366 toplevelBlock.
netlist().
connect(*ttaResetPort, *decoderDBResetPort);
1402 HDL language,
const std::string& dstDirectory,
1405 const std::string& entityString) {
1416 if (ttamachine_.isRISCVMachine()) {
1418 "ifetch-stall-cond",
1421 "ifetch-stall-port-declarations",
1427 bypassInstructionRegister());
1428 microCodeGen->
generateRTL(instantiator, dstDirectory);
1431 if (generateBusTrace()) {
1432 icGenerator_->setGenerateBusTrace(
true);
1433 icGenerator_->setBusTraceStartingCycle(busTraceStartingCycle());
1435 icGenerator_->setGenerateBusTrace(
false);
1441 if (!generateDebugger()) {
1444 "db-signal-declarations",
1445 proGeDataDir /
"no_debug_signal_declaration.snippet");
1448 if (hasSynchronousReset()) {
1449 if (language ==
VHDL) {
1451 "sync_reset_g",
"boolean",
"true");
1455 "update-condition",
"always@(posedge clk)");
1458 if (language ==
VHDL) {
1460 "sync-waitlist",
"clk, rstx");
1464 "always@(posedge clk or negedge rstx)");
1468 if (generateNoSelfLockingFUs()) {
1469 decoderGenerator_->setGenerateNoLoopbackGlock(
true);
1470 if (language ==
VHDL) {
1472 "no_glock_loopback_g",
"std_logic",
"'1'");
1477 std::size_t reqOpcodeWidth =
1478 CUOpcodeGenerator::gcuOpcodeWidth(ttamachine_);
1483 "default-instr-reg-write",
1484 Path(proGeDataDir /
"default-instr-reg-write.snippet"));
1487 std::string sensitivityStringPCBypassed =
1488 "pc_in, pc_reg, increased_pc ";
1489 std::string sensitivityStringPCNotBypassed =
"";
1491 sensitivityStringPCBypassed +=
",\n pc_load, pc_opcode";
1493 "pc-sensitivity-list-pc-bypass", sensitivityStringPCBypassed);
1496 std::string conditionString =
1497 "pc_load = '1' and ((unsigned(pc_opcode) = IFE_CALL or \n"
1498 " unsigned(pc_opcode) = IFE_JUMP))\n";
1500 "not-bypassed-next-pc-condition", conditionString);
1502 if (generateDebugger()) {
1503 if (language !=
VHDL) {
1504 std::string errorMsg =
1505 "Language not set to VHDL when HW debugger is in "
1511 "debug_logic_g",
"boolean",
"true");
1515 "db-port-declarations",
1516 Path(proGeDataDir/
"debug_minimal_port_declaration.snippet"));
1518 "db-signal-declarations",
1519 Path(proGeDataDir/
"debug_minimal_signal_declaration.snippet"));
1522 "db-port-declarations",
1523 Path(proGeDataDir/
"debug_port_declaration.snippet"));
1525 "db-signal-declarations",
1526 Path(proGeDataDir/
"debug_signal_declaration.snippet"));
1529 templateDir +
DS +
"ifetch." +
1530 (language ==
VHDL ?
"vhdl" :
"v") +
".tmpl",
1532 std::string(
"ifetch.") +
1533 (language ==
VHDL ?
"vhdl" :
"v"));
1536 templateDir +
DS +
"ifetch." +
1537 (language ==
VHDL ?
"vhdl" :
"v") +
".tmpl",
1539 std::string(
"ifetch.") +
1540 (language ==
VHDL ?
"vhdl" :
"v"));
1546 if (bypassInstructionRegister()) {
1547 if (language !=
VHDL) {
1548 std::string errorMsg =
1549 "Instruction register bypass is not supported for "
1554 addInstructioRegisterBypass(language, generator);
1558 icGenerator_->SetHDL(language);
1559 icGenerator_->generateInterconnectionNetwork(dstDirectory);
1561 decoderGenerator_->SetHDL(language);
1562 decoderGenerator_->generateInstructionDecoder(generator, dstDirectory);
1564 if (generateDebugger()) {
1565 if (language !=
VHDL) {
1566 std::string errorMsg =
1567 "Language not set to VHDL when HW debugger is in use.";
1570 generateDebuggerCode(generator);
1573 if (ttamachine_.isRISCVMachine()) {
1575 templateDir +
DS +
"rv32_ifetch.vhdl.tmpl", dstDirectory,
1579 templateDir +
DS +
"ifetch.vhdl.tmpl", dstDirectory,
1590 virtual std::set<int>
1592 return decoderGenerator_->requiredRFLatencies(iu);
1603 int requiredDelaySlots = calculateSupportedDelaySlots();
1604 int specifiedDelaySlots = ttamachine_.controlUnit()->delaySlots();
1606 if (specifiedDelaySlots != requiredDelaySlots) {
1609 TCEString(
"Decoder generator supports ") +
1611 "-stage transport pipeline of GCU with given options. "
1612 "Given machine has " +
1617 icGenerator_->verifyCompatibility();
1618 decoderGenerator_->verifyCompatibility();
1631 pkgStream <<
" -- instruction width" << endl
1632 <<
" constant INSTRUCTIONWIDTH : positive := "
1633 << bem().width() <<
";" << endl;
1635 pkgStream <<
"// instruction width" << endl
1636 <<
"parameter INSTRUCTIONWIDTH = " << bem().width()
1752 return busTraceStartingCycle();
1757 return busTraceStartingCycle();
1787 switch (direction) {
1796 return std::string();
1808 for (
int i = 0; i < ports; i++) {
1810 if (port->
width() > width) {
1811 width = port->
width();
1825 ttamachine_.isRISCVMachine() &&
1826 "Instruction register by pass only implemented for RISC-V");
1830 !generateDebugger() &&
1831 "addInstructionRegisterBypass(): "
1832 "debugger does not support Instruction Register Bypass "
1839 "bypass_fetchblock_register",
"boolean",
"true");
1844 "Verilog version of instruction register bypass "
1845 "not implemented.");
1847 assert(
false &&
"Unknown HDL choice.");
1858 if (bypassInstructionRegister()) {
1869 icGenerator_->setExportBustrace(generateDebugger());
1870 decoderGenerator_->setGenerateDebugger(generateDebugger());
1872 decoderGenerator_->setSyncReset(hasSynchronousReset());
1874 if (generateBusTrace()) {
1875 icGenerator_->setGenerateBusTrace(
true);
1876 icGenerator_->setBusTraceStartingCycle(busTraceStartingCycle());
1878 icGenerator_->setGenerateBusTrace(
false);
1879 decoderGenerator_->setGenerateBusEnable(
false);
1882 if (generateLockTrace()) {
1883 decoderGenerator_->setGenerateLockTrace(
true);
1884 decoderGenerator_->setLockTraceStartingCycle(
1885 lockTraceStartingCycle());
1887 decoderGenerator_->setGenerateLockTrace(
false);