62 auto regex = std::regex(
"\\b" + token +
"\\b");
63 return std::regex_search(line, regex);
68 auto regex = std::regex(
"\\b" + replace.first +
"\\b");
69 return std::regex_replace(line, regex, replace.second);
81 std::deque<std::string>
83 std::deque<std::string> file;
90 std::ifstream implStream(findAbsolutePath(filename));
91 for (std::string line; std::getline(implStream, line);) {
102 if (file.length() > 4 && file.substr(0, 4) ==
"tce:") {
103 file = file.substr(4);
106 for (
auto file : options_.hdbList) {
115 return "operation_in";
117 return "operation_" + std::to_string(stage) +
"_r";
124 return "load_" + triggerPort_ +
"_in";
126 return "optrig_" + std::to_string(stage) +
"_r";
132 return "op_" + operation +
"_c";
137 return operation +
"_op" + std::to_string(
id);
142 return "op" + std::to_string(
id);
148 return "data_" + port;
150 return "data_" + port +
"_" + std::to_string(cycle) +
"_r";
156 return "data_" + port +
"_" + std::to_string(cycle) +
"_valid_r";
164 if (nodeImplementations_.count(node->
nodeID())) {
165 id = nodeImplementations_[node->
nodeID()];
167 if (!subOpCount_.count(op)) {
170 id = subOpCount_[op];
171 subOpCount_[op] += 1;
172 nodeImplementations_[node->
nodeID()] = id;
174 return "subop_" + op +
"_" + std::to_string(
id);
182 if (dagConstants_.count(node->
nodeID())) {
183 id = dagConstants_[node->
nodeID()].id;
185 if (!dagConstantCount_.count(op)) {
186 dagConstantCount_[op] = 0;
188 id = dagConstantCount_[op];
189 dagConstantCount_[op] += 1;
190 dagConstants_[node->
nodeID()] = {op, node->
value(),
id};
192 return constantName(dagConstants_[node->
nodeID()]);
197 return "dag_" + dagc.
operation +
"_" + std::to_string(dagc.
id) +
"_c";
210 opName = operation->referencedOperation().name();
211 }
else if (terminal) {
213 }
else if (constant) {
216 assert(
false &&
"Shouldn't be possible to get here.");
229 fu_.appendToHeader(
"Function Unit: " + fug_.name());
230 fu_.appendToHeader(
"");
231 fu_.appendToHeader(
"Operations:");
233 if (adfFU_->operationCount() > 1) {
234 size_t maxOpNameLen = 0;
235 for (
int i = 0; i < adfFU_->operationCount(); ++i) {
237 maxOpNameLen = std::max(maxOpNameLen, hwop->
name().size());
240 static_cast<int>(std::ceil(std::log10(adfFU_->operationCount())));
241 for (
int i = 0; i < adfFU_->operationCount(); ++i) {
243 operations_.emplace_back(hwop->
name());
245 std::sort(operations_.begin(), operations_.end());
247 for (
auto&& op : operations_) {
249 std::ostringstream comment;
250 comment << boost::format(
251 " %-" + std::to_string(maxOpNameLen) +
"s : %" +
252 std::to_string(opDigits) +
"s") %
253 op % std::to_string(opcode);
254 fu_.appendToHeader(comment.str());
260 operations_.emplace_back(hwop->
name());
261 fu_.appendToHeader(
" " + hwop->
name() +
" : 0");
263 fu_.appendToHeader(
"");
268 std::string file, std::string format,
bool isSynthesizable) {
269 file = findAbsolutePath(file);
271 std::string dir = options_.outputDirectory +
DS;
272 if (isSynthesizable) {
273 dir += format ==
"VHDL" ?
"vhdl" :
"verilog";
275 dir +=
"blackbox" +
DS;
276 dir += format ==
"VHDL simulation" ?
"vhdl" :
"verilog";
292 Path dir =
Path(options_.outputDirectory) /
"vhdl";
294 Path file = dir / (fu_.name() +
".vhd");
295 std::ofstream ofs(file);
298 Path dir =
Path(options_.outputDirectory) /
"verilog";
300 Path file = dir / (fu_.name() +
".v");
301 std::ofstream ofs(file);
306 for (
auto&& opInfo : fug_.operations()) {
307 std::string hdb = opInfo.hdb;
308 hdb = findAbsolutePath(hdb);
313 for (
size_t i = 0; i < r.simFiles.size(); ++i) {
314 copyImplementation(r.simFiles[i], r.simFormats[i],
false);
316 for (
size_t i = 0; i < r.synFiles.size(); ++i) {
317 copyImplementation(r.synFiles[i], r.synFormats[i],
true);
328 std::string resetPort;
338 if (adfFU_->operationCount() > 1) {
343 for (
int i = 0; i < adfFU_->portCount(); ++i) {
349 "data_" + adfPort->
name() +
"_in", adfPort->
width(),
351 fu_ <<
InPort(
"load_" + adfPort->
name() +
"_in");
354 "data_" + adfPort->
name() +
"_out", adfPort->
width(),
359 if (addressWidth_ > 0) {
369 for (
auto&& op : operations_) {
372 int prevLatency = -1;
373 for (
int operand = 0; operand < hwOpOperands; ++operand) {
380 int latency = hwOp->
latency(operand + 1);
381 if (prevLatency == -1) {
382 prevLatency = latency;
383 }
else if (prevLatency != latency) {
385 throw std::runtime_error(
386 "FUGen cannot implement multioutput operations (" + op +
387 ") which have different latencies for"
394 std::vector<FUGen::Replace>
397 std::string op = schedule.
baseOp;
398 std::vector<FUGen::Replace> replaces;
400 replaces.emplace_back(
"glock",
"glock_in");
401 replaces.emplace_back(
"trigger", triggerSignal(schedule.
initialCycle));
403 for (
auto&& operand : schedule.
operands) {
405 replaces.emplace_back(
406 operandPlaceholder(
id), operandSignal(name,
id));
408 for (
int id : schedule.
results) {
409 replaces.emplace_back(
410 operandPlaceholder(
id), operandSignal(name,
id));
413 if (!baseOperations_.count(op)) {
418 for (
auto&& r : baseOperations_[op].resources) {
421 assert(
false &&
"Couldn't find resource offset.");
425 for (
int i = 0; i < r.count; ++i) {
427 int resID = i + offset + 1;
428 std::string file = findAbsolutePath(r.ipxact);
430 for (
auto&& p : resource.
ports) {
432 std::string replace = pName +
"_" + std::to_string(portID);
434 rName +
"_" + std::to_string(resID) +
"_" + pName;
436 replaces.emplace_back(replace, with);
442 for (
auto&& v : baseOperations_[op].variables) {
445 replica = name +
"_" + v.name;
446 replaces.emplace_back(v.name, replica);
448 bool nameFound =
false;
449 for (
auto&& old_var : renamedVariables_) {
450 if (old_var.name == v.name) {
460 renamedVariables_.emplace_back(var);
463 for (
auto&& s : baseOperations_[op].globalsignals) {
468 replica = name +
"_" + s.name;
469 replaces.emplace_back(s.name, replica);
472 bool nameFound =
false;
473 for (
auto&& old_var : renamedGlobalSignals_) {
474 if (old_var.name == s.name) {
485 renamedGlobalSignals_.emplace_back(var);
493 std::string filename, std::string opName, std::deque<std::string>& sink) {
496 std::ifstream implStream(findAbsolutePath(filename));
497 for (std::string line; std::getline(implStream, line);) {
499 for (
auto&& p : replacesPerOp_[opName]) {
500 line = replaceToken(line, p);
503 sink.emplace_back(line);
517 if (!adfFU_->hasAddressSpace()) {
521 static const std::set<std::string> magicWords{
522 "avalid",
"aready",
"aaddr",
"awren",
"astrb",
523 "rvalid",
"rready",
"rdata",
"adata"};
525 for (
auto magicWord : magicWords) {
526 if (portName.find(magicWord) != std::string::npos) {
545 if (((pos = portName.find(
"avalid")) != std::string::npos)) {
547 }
else if (((pos = portName.find(
"aready")) != std::string::npos)) {
549 }
else if (((pos = portName.find(
"aaddr")) != std::string::npos)) {
551 }
else if (((pos = portName.find(
"awren")) != std::string::npos)) {
553 }
else if (((pos = portName.find(
"astrb")) != std::string::npos)) {
555 }
else if (((pos = portName.find(
"rvalid")) != std::string::npos)) {
557 }
else if (((pos = portName.find(
"rready")) != std::string::npos)) {
559 }
else if (((pos = portName.find(
"rdata")) != std::string::npos)) {
561 }
else if (((pos = portName.find(
"adata")) != std::string::npos)) {
564 return SigT::UNDEFINED;
569 std::set<std::pair<ProGe::NetlistPort*, ProGe::NetlistPort*>> lsuPorts;
570 Replace replaceAddress = {
"addrw_c", std::to_string(addressWidth_)};
571 for (
auto&& ei : extIfaces_) {
573 for (
auto&& port : info.
ports) {
574 std::string width = port.width;
575 if (addressWidth_ > 0) {
576 width = replaceToken(width, replaceAddress);
579 if (port.direction ==
"out") {
582 extOutputs_.emplace(port.name, port.defaultValue);
587 extInputs_.emplace(port.name);
591 std::string extName = moduleName_ +
"_" + port.name;
596 if (isLSUDataPort(extName) && !genIntegrator) {
599 inferLSUSignal(extName));
600 lsuPorts.insert(std::make_pair(
internal, ext));
604 core_->netlist().connect(*ext, *
internal);
608 if (lsuPorts.empty()) {
613 if (adfFU_->hasAddressSpace()) {
614 asName = adfFU_->addressSpace()->name();
618 for (
auto portPair : lsuPorts) {
624 dmemPortGroup->
addPort(*portPair.second);
625 core_->netlist().connect(*portPair.first, *portPair.second);
627 if (dmemPortGroup !=
nullptr) {
628 core_->addPortGroup(dmemPortGroup);
629 dmemPortGroup =
nullptr;
635 std::map<std::string, int> instantiatedResources;
636 for (
auto&& rs : baseOperations_) {
637 for (
auto&& r : rs.second.resources) {
638 if (!instantiatedResources.count(r.name)) {
639 instantiatedResources[r.name] = 0;
641 std::string file = findAbsolutePath(r.ipxact);
643 int rCount = resourceCount_[rName];
645 for (
int i = instantiatedResources[r.name]; i < rCount; ++i) {
647 Module resource(module, i + 1);
650 for (
auto&& p : module.ports) {
652 rName +
"_" + std::to_string(i + 1) +
"_" + p.name);
654 fu_ <<
Wire(wName, p.width);
659 if (p.direction ==
"in") {
660 resourceInputs_.emplace_back(wName);
662 resourceOutputs_.emplace_back(wName);
666 instantiatedResources[r.name] = rCount;
678 for (
auto&& d : extOutputs_) {
682 for (std::string signal : resourceInputs_) {
684 if (isLSU_ && minLatency_ < 3) {
691 for (
auto&& pair : dagConstants_) {
692 auto spec = pair.second;
693 std::string name = constantName(spec);
698 for (std::string signal : resourceOutputs_) {
699 operationCp.
reads(signal);
702 for (std::string signal : extInputs_) {
703 operationCp.
reads(signal);
706 std::set<std::string> defaultStatements;
707 for (
auto&& pair : scheduledOperations_) {
708 auto schedule = pair.second;
709 std::string name = pair.first;
711 for (
int id : schedule.results) {
712 std::string source = operandSignal(name,
id);
714 if (isLSU_ && minLatency_ < 3) {
721 for (
auto&& operand : schedule.operands) {
724 std::string source = operand.signalName;
725 std::string destination = operandSignal(name,
id);
726 if (operand.portWidth > operand.operandWidth) {
729 Splice(source, operand.operandWidth - 1, 0)));
730 }
else if (operand.portWidth < operand.operandWidth) {
733 Ext(source, operand.operandWidth, operand.portWidth)));
738 if (!operand.isOutput) {
739 operationCp.
reads(destination);
743 replacesPerOp_[name] = buildReplaces(name);
745 std::string baseOp = schedule.baseOp;
746 auto& initial = baseOperations_[baseOp].initial;
747 if (!initial.empty()) {
748 prepareSnippet(name, initial, defaultSnippets, defaultStatements);
752 for (
int cycle = 0; cycle <= maxLatency_; ++cycle) {
754 bool emptySwitch =
true;
756 for (std::string op : operations_) {
758 bool emptyBlock =
true;
759 auto schedule = scheduledOperations_[op];
761 std::vector<std::string> schedules = schedule.subOperations;
762 schedules.push_back(op);
764 for (std::string subop : schedules) {
765 auto schedule = scheduledOperations_[subop];
766 std::string baseOp = schedule.baseOp;
767 if (schedule.initialCycle == cycle) {
768 auto& impl = baseOperations_[baseOp].implementation;
770 std::set<std::string> statements;
771 prepareSnippet(subop, impl, onTrigger, statements);
776 if (schedule.finalCycle == cycle) {
777 auto& postOp = baseOperations_[baseOp].postOp;
778 if (!postOp.empty()) {
779 std::set<std::string> statements;
780 prepareSnippet(subop, postOp, onTrigger, statements);
790 if (operations_.size() > 1) {
791 Case opCase(opcodeConstant(op));
800 triggeredSnippets.
append(opIf);
809 triggeredSnippets.
append(opIf);
814 operationCp.
reads(
"glock_in");
817 if (useGlockRequest_) {
821 for (
auto&& v : renamedVariables_) {
822 int w = std::stoi(v.width);
823 if (v.type ==
"Logic") {
825 }
else if (v.type ==
"Unsigned") {
831 if (isLSU_ && minLatency_ < 3) {
837 for (
auto&& s : renamedGlobalSignals_) {
838 int w = std::stoi(s.width);
839 fu_ <<
Wire(s.name, w);
840 operationCp.
reads(s.name);
842 if (isLSU_ && minLatency_ < 3) {
849 operationCp << defaultValues << defaultSnippets << triggeredSnippets;
850 behaviour_ << operationCp;
855 std::string name, std::deque<std::string> statements,
CodeBlock& sink,
856 std::set<std::string>& addedStatements) {
857 std::deque<std::string> snippet;
858 std::set<std::string> lines;
859 for (std::string line : statements) {
861 for (
Replace rep : replacesPerOp_[name]) {
862 replaced = replaceToken(replaced, rep);
866 if (addedStatements.count(replaced)) {
869 lines.insert(replaced);
871 snippet.push_back(replaced);
873 if (hasToken(line,
"glockreq")) {
874 useGlockRequest_ =
true;
876 if (hasToken(line,
"glock")) {
881 for (std::string line : lines) {
882 addedStatements.insert(line);
891 if (useGlockRequest_) {
892 fu_ <<
Wire(
"glockreq");
900 for (
auto&& option : globalOptions_) {
908 std::vector<std::string> dagOperations;
910 for (
auto&& op : fug_.operations()) {
912 opInfo.
name = op.operationName;
915 std::string opHDB = findAbsolutePath(op.hdb);
921 std::string implFile;
930 const std::string msg =
931 "Cannot generate operation \"" + opInfo.
name +
932 "\" due to missing verilog operation implementation";
933 throw std::runtime_error(msg);
943 implLatency_[opInfo.
name] = op.latency;
945 baseOperations_.emplace(opInfo.
name, opInfo);
948 if (!ifPath.empty()) {
949 extIfaces_.insert(findAbsolutePath(ifPath));
954 minLatency_ = INT_MAX;
955 for (
auto&& op : operations_) {
960 for (
int operand = 0; operand < hwOpOperands; ++operand) {
964 std::string portName = fuPort->
name();
965 int latency = hwOp->
latency(operand + 1);
967 auto search = operationCycles_.find(op);
968 if (search != operationCycles_.end()) {
969 operationCycles_[op] = std::max(search->second, latency);
971 operationCycles_[op] = latency;
973 maxLatency_ = std::max(maxLatency_, latency);
974 minLatency_ = std::min(minLatency_, latency);
978 if (baseOperations_.find(op) == baseOperations_.end()) {
979 dagOperations.emplace_back(op);
983 for (
auto&& op : dagOperations) {
992 throw std::runtime_error(op +
" has no dags to implement.");
995 bool implementable =
false;
996 for (
int i = 0; i < dagCount; ++i) {
1002 dagPtr = &osalOp->
dag(i);
1006 *dagPtr, fug_.operations(),
nullptr)) {
1009 implementable =
true;
1010 implementapleDAGs_[op] = dagPtr;
1017 if (!implementable) {
1018 throw std::runtime_error(op +
" has no valid dags to implement.");
1028 int srcWidth = DAGNodeOperandWidth(srcNode, srcID, dag);
1032 int dstWidth = DAGNodeOperandWidth(dstNode, dstID, dag);
1033 auto dstTerminal =
dynamic_cast<TerminalNode*
>(&dstNode);
1042 std::string signalName;
1044 std::string srcOp = subOpName(operation);
1046 signalName = operandSignal(srcOp, srcID);
1047 }
else if (terminal) {
1050 srcID = terminal->operandIndex();
1051 signalName = operandSignal(srcOp, srcID);
1052 }
else if (constant) {
1053 signalName = constantName(constant, dag);
1055 assert(
false &&
"It shouldn't be possible to get here.");
1059 dstID, srcWidth, dstWidth, signalName, isOutput};
1065 std::set<std::string> instantiatedWires;
1066 for (
auto&& op : operations_) {
1070 if (frontRegistered_) {
1071 schedule.
initialCycle = operationCycles_[op] - implLatency_[op];
1073 }
else if (middleRegistered_) {
1075 operationCycles_[op] - implLatency_[op] - 1;
1083 "Failure likely due to mis-selected operation implementation");
1091 std::string port = fuPort->
name();
1092 int width = osalOperand.
width();
1097 i, fuPort->
width(), width,
1104 accessCycle = operationCycles_[op] - schedule.
finalCycle;
1108 width, i, schedule.
finalCycle, accessCycle, op};
1109 portInputs_.emplace(port, out);
1114 "Failure likely due to mis-selected operation "
1117 std::string newWire = operandSignal(op, i);
1118 if (!instantiatedWires.count(newWire)) {
1119 fu_ <<
Wire(newWire, width);
1120 instantiatedWires.insert(newWire);
1123 if (pipelineLength_.find(port) == pipelineLength_.end()) {
1124 pipelineLength_[port] = accessCycle;
1126 pipelineLength_[port] =
1127 std::max(accessCycle, pipelineLength_[port]);
1130 if (portDirection_.find(port) == portDirection_.end()) {
1131 portDirection_[port] = dir;
1133 if (portDirection_[port] != dir) {
1134 throw std::runtime_error(
1135 "Unsupported bidirectional port " + port +
1141 if (baseOperations_.find(op) != baseOperations_.end()) {
1144 for (
auto&& res : baseOperations_[op].resources) {
1147 resourceCount_[res.name] =
1148 std::max(resourceCount_[res.name], res.count);
1151 assert(implementapleDAGs_.find(op) != implementapleDAGs_.end());
1152 auto dag = implementapleDAGs_[op];
1153 std::unordered_map<std::string, int> dagResourceCount;
1155 for (
int n = 0; n < dag->nodeCount(); ++n) {
1162 if (!operationNode) {
1170 std::string name = subOpName(operationNode);
1172 subopSchedule.
baseOp = subOp;
1177 *dag, node, implLatency_,
false);
1181 for (
auto&& input : dag->inEdges(node)) {
1182 int dstID = input->dstOperand();
1183 int width = DAGNodeOperandWidth(
1184 dag->headNode(*input), dstID, dag);
1186 std::string newWire = operandSignal(name, dstID);
1187 if (!instantiatedWires.count(newWire)) {
1188 fu_ <<
Wire(newWire, width);
1189 instantiatedWires.insert(newWire);
1193 subOpConnection(dag, input,
false));
1196 for (
auto&& output : dag->outEdges(node)) {
1197 int srcID = output->srcOperand();
1198 int width = DAGNodeOperandWidth(
1199 dag->tailNode(*output), srcID, dag);
1201 std::string newWire = operandSignal(name, srcID);
1202 if (!instantiatedWires.count(newWire)) {
1203 fu_ <<
Wire(newWire, width);
1204 instantiatedWires.insert(newWire);
1207 subopSchedule.
results.insert(srcID);
1214 subOpConnection(dag, output,
true));
1220 for (
auto&& r : baseOperations_[subOp].resources) {
1222 if (!dagResourceCount.count(resName)) {
1223 dagResourceCount[resName] = 0;
1226 dagResourceCount[resName];
1227 dagResourceCount[resName] += r.count;
1230 scheduledOperations_[name] = subopSchedule;
1233 for (
auto&& d : dagResourceCount) {
1234 resourceCount_[d.first] =
1235 std::max(resourceCount_[d.first], d.second);
1238 scheduledOperations_[op] = schedule;
1244 std::vector<std::string> inOperands;
1245 std::unordered_set<std::string> registeredInOperands;
1246 std::unordered_map<std::string, std::string> currentName;
1247 std::unordered_map<std::string, int> portWidth;
1249 for (
int i = 0; i < adfFU_->portCount(); ++i) {
1252 portWidth[adfPort->
name()] = adfPort->
width();
1255 currentName[adfPort->
name()] =
"data_" + adfPort->
name() +
"_in";
1258 triggerPort_ = adfPort->
name();
1261 inOperands.emplace_back(adfPort->
name());
1263 registeredInOperands.emplace(adfPort->
name());
1266 std::string name = pipelineName(adfPort->
name(), 0);
1269 currentName[adfPort->
name()] =
"data_" + adfPort->
name() +
"_out";
1274 for (
auto&& p : inOperands) {
1275 std::string newName =
"data_" + p +
"_gated";
1277 Sext(
"load_" + p +
"_in", portWidth[p], 1);
1278 behaviour_ <<
Assign(newName, gate);
1279 currentName[p] = newName;
1280 fu_ <<
Wire(newName, portWidth[p]);
1284 for (
auto&& p : inOperands) {
1285 std::string dataPort = currentName[p];
1286 std::string output = pipelineName(p, 0);
1287 if (p != triggerPort_ &&
1288 registeredInOperands.find(p) != registeredInOperands.end()) {
1289 std::string loadPort =
"load_" + p +
"_in";
1290 std::string shadowReg =
"shadow_" + p +
"_r";
1299 behaviour_ << (
Synchronous(
"shadow_" + p +
"_sp") << iffi);
1301 auto triggerLoad =
Equals(
1302 LHSSignal(
"load_" + triggerPort_ +
"_in"),
1305 triggerLoad && portLoad,
1309 behaviour_ << (
Asynchronous(
"shadow_" + p +
"_cp") << cpIf);
1324 for (
int i = 0; i < maxLatency_; ++i) {
1325 if (operations_.size() > 1) {
1326 std::string prevOpcode = opcodeSignal(i);
1327 std::string nextOpcode = opcodeSignal(i + 1);
1332 pipelineAssignments.
append(
1336 std::string prevTrigger = triggerSignal(i);
1337 std::string nextTrigger = triggerSignal(i + 1);
1338 addRegisterIfMissing(nextTrigger, 1);
1339 pipelineAssignments.
append(
1344 for (
int i = 0; i < adfFU_->portCount(); ++i) {
1345 auto port = adfFU_->port(i);
1346 int length = pipelineLength_[port->name()];
1347 int width = port->width();
1352 for (
int i = 0; i < length; ++i) {
1353 std::string prevReg = pipelineName(port->name(), i);
1354 std::string nextReg = pipelineName(port->name(), i + 1);
1359 pipelineAssignments.
append(
1365 If operationTrigger(
1367 pipelineAssignments.
append(operationTrigger);
1370 pipelineAssignments);
1372 pipeline << glock_low;
1373 behaviour_ << pipeline;
1380 registers_.emplace_back(name);
1389 for (
int i = 0; i < adfFU_->portCount(); ++i) {
1390 auto port = adfFU_->port(i);
1391 int length = pipelineLength_[port->name()];
1392 int width = port->
width();
1397 auto inputs = portInputs_.equal_range(port->name());
1398 for (
int cycle = length; cycle >= 0; --cycle) {
1399 bool cycleActive =
false;
1401 std::string nextReg = pipelineName(port->name(), cycle);
1402 std::string prevReg = pipelineName(port->name(), cycle + 1);
1403 std::string valid = pipelineValid(port->name(), cycle);
1410 addRegisterIfMissing(valid, 1);
1415 for (
auto it = inputs.first; it != inputs.second; ++it) {
1416 auto connection = it->second;
1417 if (connection.pipelineStage != cycle) {
1422 LHSSignal(triggerSignal(connection.sourceCycle)),
1426 LHSSignal(opcodeSignal(connection.sourceCycle)),
1427 LHSSignal(opcodeConstant(connection.operation))),
1431 operandSignal(connection.operation, connection.operandID),
1432 width, connection.operandWidth);
1435 if (operations_.size() == 1) {
1437 triggered,
Assign(nextReg, source));
1440 active,
Assign(nextReg, source));
1443 if (operations_.size() == 1) {
1445 If(triggered,
Assign(nextReg, source));
1447 validOperations =
If(active,
Assign(nextReg, source));
1453 bool skip_last_assign =
false;
1455 if (cycle != length) {
1456 std::string prevValid =
1457 pipelineValid(port->name(), cycle + 1);
1465 skip_last_assign =
true;
1476 std::string outReg = nextReg +
"_r";
1481 if (!skip_last_assign) {
1484 lastStage.
append(validOperations);
1486 lastStage.
append(finalStep);
1491 outputPipeline.
append(validOperations);
1495 "data_" + port->name() +
"_out",
1496 LHSSignal(pipelineName(port->name(), 0))));
1506 behaviour_ << async;
1517 const std::vector<IDF::FUGenerated>& generatetFUs,
1520 for (
auto fug : generatetFUs) {
1526 fug.name(),
options.fuFrontRegistered,
false)) {
1529 fug.name(),
options.fuMiddleRegistered,
false)) {
1532 fug.name(),
options.fuBackRegistered,
false)) {
1535 fug.name(),
options.fuFrontRegistered)) {
1538 fug.name(),
options.fuMiddleRegistered)) {