OpenASIP 2.2
Loading...
Searching...
No Matches
HDLGenerator.hh
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2017 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25* @file HDLGenerator.hh
26*
27* @author Lasse Lehtonen 2017 (lasse.lehtonen-no.spam-tut.fi)
28*/
29#pragma once
30#include "IPXact.hh"
31#include "HWGenTools.hh"
32#include "LHSValue.hh"
33#include "HDLRegister.hh"
34#include "Generatable.hh"
35#include "HDLPort.hh"
36#include "StringTools.hh"
37#include "LicenseGenerator.hh"
38#include <boost/format.hpp>
39#include <chrono>
40#include <cmath>
41#include <ctime>
42#include <deque>
43#include <iomanip>
44#include <iostream>
45#include <memory>
46#include <sstream>
47#include <string>
48#include <unordered_map>
49#include <unordered_set>
50#include <vector>
51#include <type_traits>
52
53namespace HDLGenerator {
54
55 /** @page hdl_generator HDLGenerator
56 *
57 * <pre>
58 * Basic idea of HDLGenerator is to construct objects (modules, ports,
59 * behavioral code constructs, etc), assign them to the object wich they
60 * logically belong to, and finally call implement for the module.
61 * Calling implement builds the code, does some limited validity checks,
62 * and spits either Verilog or VHDL.
63 *
64 * Only a limited subset of code constructs are present as not all were
65 * relevant for efficient hdl.
66 *
67 * Some options can be used to guide the generation:
68 * "asynchronous reset" - Self-explanatory.
69 * "synchronous reset" - Self-explanatory.
70 * "reset everything" - Without this only registers with
71 * ResetOption::Mandatory will be assigned a value
72 * in reset.
73 *
74 * What can be assigned to:
75 * Module << Register / Wire / InPort / OutPort / Parameter / Option
76 * Module << (std::string comment) / BinaryConstant / IntegerConstant
77 * Module << Behaviour / Module
78 * Behaviour << Assign / Asynchronous / Synchronous
79 * Asynchronous / Synchronous << SequentialStatement / Variable
80 * If << Else / SequentialStatement
81 * Switch << Case / DefaultCase
82 * Case / DefaultCase << HDLOperation / Assign / If
83 *
84 * Case clauses:
85 * Case / DefaultCase << BinaryLiteral / (int) / (std::string)
86 * </pre>
87 *
88 *
89 *
90 */
91
92 class Module;
93 class Behaviour;
94 class Synchronous;
95 class Asynchronous;
96 class Option;
97 class Assign;
98 class Wire;
99 class LogicVariable;
100 class SignedVariable;
101 class UnsignedVariable;
102 class IntegerConstant;
103 class CastLogicToUnsigned;
104 class CastLogicToSigned;
105 class BinaryConstant;
106 class Parameter;
107 class InPort;
108 class OutPort;
109 class If;
110 class Else;
111 class Switch;
112 class Case;
113 class DefaultCase;
114 class Splice;
115 class RawCodeLine;
116 class HDLOperation;
117 class CodeBlock;
118
119 /**
120 * Base class for concurrent statements and code blocks
121 */
123 public:
125
126 virtual void hdl(std::ostream& stream, Language lang, int level) {
127 (void)stream;
128 (void)lang;
129 (void)level;
130 std::string err =
131 std::string("Attempted to generate virtual class");
132 throw std::runtime_error(err);
133 }
134 private:
135 std::string altname;
136 };
137
138 /**
139 * Represents VHDL operation snippet.
140 */
142 public:
144 HDLOperation(std::string name, std::deque<std::string> impl,
145 Language lang)
146 : SequentialStatement(name), impl_(std::move(impl)), lang_(lang) {}
147
148 HDLOperation& operator<<(const std::string& rhs) {
149 readList_.emplace_back(rhs);
150 return *this;
151 }
152
153 HDLOperation& operator<<(const std::string&& rhs) {
154 readList_.emplace_back(rhs);
155 return *this;
156 }
157
158 void build() override {
160 for (auto&& r : readList_) {
161 reads(r);
162 }
163 }
164
165 void hdl(std::ostream& stream, Language lang, int level) override {
166 if (lang != lang_)
167 throw std::runtime_error(__PRETTY_FUNCTION__);
168
169 for (auto&& line : impl_) {
170 stream << StringTools::indent(level) << line << "\n";
171 }
172 }
173
174 private:
175 std::deque<std::string> impl_;
176 std::vector<std::string> readList_;
178 };
179
180
181 /**
182 * Raw code.
183 */
185 public:
186 RawCodeLine(std::string vhdl, std::string verilog)
187 : SequentialStatement("raw code line"),
188 vhdl_(vhdl), verilog_(verilog) {}
189
190 void hdl(std::ostream& stream, Language lang, int level) final {
191 if (lang == Language::VHDL) {
192 stream << StringTools::indent(level) << vhdl_ << "\n";
193 } else if (lang == Language::Verilog) {
194 stream << StringTools::indent(level) << verilog_ << "\n";
195 } else {
196 throw std::runtime_error(__PRETTY_FUNCTION__);
197 }
198 }
199
200 private:
201 std::string vhdl_;
202 std::string verilog_;
203 };
204
205 /**
206 * Option.
207 */
208 class Option : public Generatable {
209 public:
210 Option(std::string name) : Generatable(name) {}
211 };
212
213 /**
214 * Generic/parameter.
215 */
216 class Parameter : public Generatable {
217 public:
218 Parameter(std::string name, int value = -1)
219 : Generatable(name), value_(value) {}
220 Parameter(std::string name, std::string value)
221 : Generatable(name), value_(-1), strValue_(value) {}
222
223 Width width() final { return {name(), value_}; }
224 std::string strValue() { return strValue_; }
225
226 void declare(std::ostream& stream, Language lang, int level = 0) {
227 stream << StringTools::indent(level);
228 if (lang == Language::VHDL) {
229 stream << name() << " : integer";
230 } else if (lang == Language::Verilog) {
231 stream << "parameter integer " << name();
232 } else {
233 throw std::runtime_error(__PRETTY_FUNCTION__);
234 }
235 }
236
237 private:
239 std::string strValue_;
240 };
241
242 /**
243 * Binary constant.
244 */
246 public:
247 BinaryConstant(std::string name, int width, int value)
249
250 int value() const noexcept { return value_; }
251
252 Width width() final { return {name(), width_}; }
253
254 void declare(std::ostream& stream, Language lang, int level) {
255 std::string binVal = "";
256 int tempVal = value_;
257 for (int i = width_ - 1; i >= 0; --i) {
258 long power = static_cast<long>(std::pow(2, i));
259 if (power <= tempVal) {
260 tempVal -= power;
261 binVal += "1";
262 } else {
263 binVal += "0";
264 }
265 }
266
267 if (lang == Language::VHDL) {
268 stream << StringTools::indent(level) << "constant " << name()
269 << " : std_logic_vector(" << width_ - 1
270 << " downto 0) := \"" << binVal << "\";\n";
271 } else if (lang == Language::Verilog) {
272 stream << StringTools::indent(level)
273 << "localparam [" << width_-1 << ":0] "
274 << name() << " = " << width_ << "'b" << binVal << ";\n";
275 } else {
276 throw std::runtime_error(__PRETTY_FUNCTION__);
277 }
278 }
279
280 private:
283 };
284
285 /**
286 * Integer constant.
287 */
289 public:
290 IntegerConstant(std::string name, int value)
292
293 int value() const noexcept { return value_; }
294
295 Width width() final { return {name(), value_}; }
296
297 void declare(std::ostream& stream, Language lang, int level) {
298 if (lang == Language::VHDL) {
299 stream << StringTools::indent(level) << "constant " << name()
300 << " : integer := " << value() << ";\n";
301 } else if (lang == Language::Verilog) {
302 stream << StringTools::indent(level) << "localparam integer "
303 << name() << " = " << value() << ";\n";
304 } else {
305 throw std::runtime_error(__PRETTY_FUNCTION__);
306 }
307 }
308
309 private:
311 };
312
313 /**
314 * Async signal/wire.
315 */
316 class Wire : public Generatable {
317 public:
318 Wire(std::string name, int width = 1, WireType wt = WireType::Auto)
319 : Generatable(name), width_(width), wt_(wt) {}
320 Wire(std::string name, std::string width)
322
323 Width width() final { return {strWidth_, width_}; }
324
325 void declare(std::ostream& stream, Language lang, int ident) {
326 if (lang == Language::VHDL) {
327 stream << StringTools::indent(ident) << "signal "
328 << name() << " : ";
329 if (width_ < 0 || width_ > 1 || wt_ == WireType::Vector) {
330 if (strWidth_.empty()) {
331 stream << "std_logic_vector("
332 << std::to_string(width_ - 1)
333 << " downto 0);\n";
334 } else {
335 stream << "std_logic_vector(" << strWidth_
336 << "-1 downto 0);\n";
337 }
338 } else {
339 stream << "std_logic;\n";
340 }
341 } else if (lang == Language::Verilog) {
342 stream << StringTools::indent(ident) << "reg ";
343 if (width_ < 0 || width_ > 1) {
344 if (strWidth_.empty()) {
345 stream << "[" << std::to_string(width_ - 1) << ":0] ";
346 } else {
347 stream << "[" << strWidth_ << "-1:0] ";
348 }
349 }
350 stream << name() << ";\n";
351 } else {
352 throw std::runtime_error(__PRETTY_FUNCTION__);
353 }
354 }
355
356 WireType wireType() const final { return wt_; }
357
358 private:
359 std::string strWidth_;
362 };
363
364 /**
365 * Assign default value.
366 */
368 public:
369 DefaultAssign(std::string name, std::string value)
371 DefaultAssign(std::string name)
372 : SequentialStatement(name), value_(""), dontCare_(true) {}
373
374 void hdl(std::ostream& stream, Language lang, int level) override {
375 Width w = width(name());
376 WireType t = wireType(name());
377
378
379 if (lang == Language::VHDL) {
380 std::string def = "-";
381 if (!dontCare_)
382 def = value_.substr(0, 1);
383
384 std::string assign = " <= ";
385 if (isVariable(name())) {
386 assign = " := ";
387 }
388 stream << StringTools::indent(level) << name() << assign;
389
390 if (w.strWidth.empty() && w.intWidth == 1) {
391 char delim = t == WireType::Auto ? '\'' : '"';
392 stream << delim << def << delim << ";\n";
393 } else {
394 stream << "(others => '" << def << "');\n";
395 }
396 } else if (lang == Language::Verilog) {
397 std::string def = "x";
398 if (!dontCare_)
399 def = value_.substr(0, 1);
400
401 stream << StringTools::indent(level)
402 << name() << " = 'b" << def << ";\n";
403 } else {
404 throw std::runtime_error(__PRETTY_FUNCTION__);
405 }
406 }
407
408 private:
409 std::string value_;
411 };
412
413
414 class Variable : public Generatable {
415 public:
416 Variable(std::string name, int width = 1)
417 : Generatable(name), strWidth_(std::to_string(width)),
419 Variable(std::string name, std::string width)
422
423 Width width() final { return {strWidth_, width_}; }
424
425 void declare(std::ostream& stream, Language lang, int level) {
426 if (lang == Language::VHDL) {
427 stream << StringTools::indent(level) << "variable " << name()
428 << " : " << vhdlTypeDeclaration() << ";\n";
429 } else if (lang == Language::Verilog) {
430 stream << StringTools::indent(level)
432 << " " << name() << ";\n";
433 } else {
434 throw std::runtime_error(__PRETTY_FUNCTION__);
435 }
436 }
437
438 std::string vhdlRange() {
439 std::string width = strWidth_;
440 if (width.empty()) {
441 width = std::to_string(width_);
442 }
443 return "(" + width + "-1 downto 0)";
444 }
445
446 std::string verilogRange() {
447 std::string width = strWidth_;
448 if (width.empty()) {
449 width = std::to_string(width_);
450 }
451 return "[" + width + "-1:0] ";
452 }
453
454 virtual std::string vhdlTypeDeclaration() {
455 throw std::runtime_error(__PRETTY_FUNCTION__);
456 }
457
459 std::string decl = "reg";
460 if (isVector()) {
461 decl += " " + verilogRange();
462 }
463 return decl;
464 }
465
466 bool isVector() {
467 return wireType_ == WireType::Vector || width_ > 1;
468 }
469
471 return wireType_;
472 }
473
474 private:
475 std::string strWidth_;
478 };
479
480 /**
481 * Variable/async reg.
482 */
483 class LogicVariable : public Variable {
484 public:
485 LogicVariable(std::string name, int width = 1)
486 : Variable(name, width) {}
487 LogicVariable(std::string name, std::string width)
488 : Variable(name, width) {}
489
490 std::string vhdlTypeDeclaration() {
491 if (isVector()) {
492 return "std_logic_vector" + vhdlRange();
493 } else {
494 return "std_logic";
495 }
496 }
497 };
498
499 /**
500 * Unsigned variable/async reg.
501 */
502 class UnsignedVariable : public Variable {
503 public:
504 UnsignedVariable(std::string name, int width = 1)
505 : Variable(name, width) {}
506 UnsignedVariable(std::string name, std::string width)
507 : Variable(name, width) {}
508
509 std::string vhdlTypeDeclaration() {
510 return "unsigned" + vhdlRange();
511 }
512 };
513
514 /**
515 * Signed variable/async reg signed.
516 */
517 class SignedVariable : public Variable {
518 public:
519 SignedVariable(std::string name, int width = 1)
520 : Variable(name, width) {}
521 SignedVariable(std::string name, std::string width)
522 : Variable(name, width) {}
523
524 std::string vhdlTypeDeclaration() {
525 return "signed" + vhdlRange();
526 }
527
529 std::string decl = "reg signed";
530 if (isVector()) {
531 decl += " " + verilogRange();
532 }
533 return decl;
534 }
535 };
536
537 /**
538 * Assignment.
539 */
541 public:
542 Assign(std::string var, LHSValue value)
543 : SequentialStatement(var), index_(-1), upperBound_(-1),
544 lowerBound_(-1), value_(value) {}
545 Assign(std::string var, LHSValue value, int idx)
546 : SequentialStatement(var), index_(idx), upperBound_(-1),
547 lowerBound_(-1), value_(value) {}
548 Assign(std::string var, LHSValue value, int ub, int lb)
549 : SequentialStatement(var), index_(-1), upperBound_(ub),
550 lowerBound_(lb), value_(value) {}
551
552 void build() override {
554 writes(name());
555 reads(value_);
556 }
557
558 void hdl(std::ostream& stream, Language lang, int level) override {
559 if (isRegister(name()) && !parentIs<Synchronous>()) {
560 throw std::runtime_error(
561 "assigning to register '" + name() +
562 "' is only allowed in synchronous context");
563 } else if (isVariable(name()) && (!parentIs<Synchronous>() ||
564 !parentIs<Asynchronous>())) {
565 throw std::runtime_error("Not allowed to assign to '" +
566 name() + "' in this context.");
567 }
568 if (lang == Language::VHDL) {
569 stream << StringTools::indent(level) << name();
570 if (upperBound_ >= 0) {
571 stream << "(" << upperBound_ << " downto "
572 << lowerBound_ << ")";
573 } else if (index_ >= 0) {
574 stream << "(" << index_ << ")";
575 }
576 if (isVariable(name())) {
577 stream << " := ";
578 } else {
579 stream << " <= ";
580 }
581 } else if (lang == Language::Verilog) {
582 if (!(parentIs<Synchronous>() || parentIs<Asynchronous>())) {
583 stream << StringTools::indent(level) << "always @*\n"
584 << StringTools::indent(level + 1) << name();
585 } else {
586 stream << StringTools::indent(level) << name();
587 }
588 if (upperBound_ >= 0) {
589 stream << "[" << upperBound_ << ":" << lowerBound_ << "]";
590 } else if (index_ >= 0) {
591 stream << "[" << index_ << "]";
592 }
593 if (isRegister(name())) {
594 stream << " <= ";
595 } else {
596 stream << " = ";
597 }
598 } else {
599 throw std::runtime_error(__PRETTY_FUNCTION__);
600 }
601 value_.hdl(stream, lang);
602 stream << ";\n";
603 }
604
605 private:
610 };
611
612 /**
613 * When others/default.
614 */
615 class DefaultCase : public Generatable {
616 public:
617 DefaultCase() : Generatable("defaultCase") {}
618
620 addComponent(rhs);
621 return *this;
622 }
623
625 addComponent(rhs);
626 return *this;
627 }
628
629 void hdl(std::ostream& stream, Language lang, int level) override {
630 if (lang == Language::VHDL) {
631 stream << StringTools::indent(level) << "when others =>\n";
632 implementAll(stream, lang, level);
633 } else if (lang == Language::Verilog) {
634 stream << StringTools::indent(level) << "default: begin\n";
635 implementAll(stream, lang, level);
636 stream << StringTools::indent(level) << "end\n";
637 } else {
638 throw std::runtime_error(__PRETTY_FUNCTION__);
639 }
640 }
641 };
642
643 /**
644 * Case in a switch-case.
645 */
646 class Case : public Generatable {
647 public:
648 Case() : Generatable("case") {}
649 Case(std::string stringCase) : Generatable("case"),
650 stringCase_(stringCase) {}
651
652 template<typename SS>
653 Case& operator<<(SS op) {
654 std::shared_ptr<SequentialStatement> ptr = std::make_shared<SS>(op);
655 pushComponent(ptr);
656 return *this;
657 }
658
660 binaryCases_.emplace_back(rhs);
661 return *this;
662 }
663
665 binaryCases_.emplace_back(rhs);
666 return *this;
667 }
668
669 Case& operator<<(int rhs) {
670 intCases_.emplace_back(rhs);
671 return *this;
672 }
673
674 Case& operator<<(std::string& rhs) {
675 stringCase_ = rhs;
676 return *this;
677 }
678
679 Case& operator<<(std::string&& rhs) {
680 stringCase_ = rhs;
681 return *this;
682 }
683
684 void hdl(std::ostream& stream, Language lang, int level) override {
685 if (lang == Language::VHDL) {
686 stream << StringTools::indent(level) << "when ";
687 if (!stringCase_.empty()) {
688 stream << stringCase_;
689 } else if (!intCases_.empty()) {
690 std::string separator = "";
691 for (auto&& c : intCases_) {
692 stream << separator << std::to_string(c);
693 separator = " | ";
694 }
695 } else if (!binaryCases_.empty()) {
696 std::string separator = "";
697 for (auto&& c : binaryCases_) {
698 stream << separator;
699 c.hdl(stream, lang);
700 separator = " | ";
701 }
702 } else {
703 throw std::runtime_error("Case has no case");
704 }
705 stream << " =>\n";
706 implementAll(stream, lang, level + 1);
707 } else if (lang == Language::Verilog) {
708 stream << StringTools::indent(level);
709 if (!stringCase_.empty()) {
710 stream << stringCase_;
711 } else if (!intCases_.empty()) {
712 std::string separator = "";
713 for (auto&& c : intCases_) {
714 stream << separator << std::to_string(c);
715 separator = ", ";
716 }
717 } else if (!binaryCases_.empty()) {
718 std::string separator = "";
719 for (auto&& c : binaryCases_) {
720 stream << separator;
721 c.hdl(stream, lang);
722 separator = ", ";
723 }
724 } else {
725 throw std::runtime_error("Case has no case");
726 }
727 stream << ": begin\n";
728 implementAll(stream, lang, level + 1);
729 stream << StringTools::indent(level) << "end\n";
730 } else {
731 throw std::runtime_error(__PRETTY_FUNCTION__);
732 }
733 }
734
735 private:
736 std::string stringCase_;
737 std::vector<int> intCases_;
738 std::vector<BinaryLiteral> binaryCases_;
739 };
740
741 /**
742 * Switch-case switch.
743 */
745 public:
746 Switch(LHSValue control) : SequentialStatement("switch"),
747 control_(control) {}
748
749 void addCase(Case rhs) {
750 addComponent(rhs);
751 }
752
754 addComponent(rhs);
755 }
756
757 void build() override {
760 }
761
762 void hdl(std::ostream& stream, Language lang, int level) override {
763 if (lang == Language::VHDL) {
764 stream << StringTools::indent(level) << "case ";
765 control_.hdl(stream, lang);
766 stream << " is\n";
767 implementAll(stream, lang, level + 1);
768 stream << StringTools::indent(level) << "end case;\n";
769 } else if (lang == Language::Verilog) {
770 stream << StringTools::indent(level) << "case (";
771 control_.hdl(stream, lang);
772 stream << ")\n";
773 implementAll(stream, lang, level + 1);
774 stream << StringTools::indent(level) << "endcase\n";
775 } else {
776 throw std::runtime_error(__PRETTY_FUNCTION__);
777 }
778 }
779
780 private:
782 };
783
784 /**
785 * if/elsif/else.
786 */
787 class If : public SequentialStatement {
788 public:
789 template<typename SS>
790 If(LHSValue cls, SS ifBlock) : SequentialStatement("if"),
791 elseBlock_(nullptr) {
792 std::shared_ptr<SequentialStatement> ptr
793 = std::make_shared<SS>(ifBlock);
794 ifBlocks_.emplace_back(cls, ptr);
795 }
796
797 template<typename SS>
798 void elseIfClause(LHSValue cls, SS ifBlock) {
799 std::shared_ptr<SequentialStatement> ptr
800 = std::make_shared<SS>(ifBlock);
801 ifBlocks_.emplace_back(cls, ptr);
802 }
803
804 template<typename SS>
805 void elseClause(SS elseBlock) {
806 if (elseBlock_) {
807 throw std::runtime_error("Cannot to add a second else block.");
808 }
809 std::shared_ptr<SequentialStatement> ptr
810 = std::make_shared<SS>(elseBlock);
811 elseBlock_ = ptr;
812 }
813
814 virtual void hdl(std::ostream& stream, Language lang, int level)
815 override {
816 if (lang == Language::VHDL) {
817 for (auto iter = ifBlocks_.begin(); iter != ifBlocks_.end();
818 ++iter) {
819 if (iter == ifBlocks_.begin()) {
820 stream << StringTools::indent(level) << "if ";
821 } else {
822 stream << StringTools::indent(level) << "elsif ";
823 }
824 iter->first.hdl(stream, lang);
825 stream << " then\n";
826 iter->second->hdl(stream, lang, level + 1);
827 }
828 if (elseBlock_ != nullptr) {
829 stream << StringTools::indent(level) << "else\n";
830 elseBlock_->hdl(stream, lang, level + 1);
831 }
832 stream << StringTools::indent(level) << "end if;\n";
833 } else if (lang == Language::Verilog) {
834 for (auto iter = ifBlocks_.begin(); iter != ifBlocks_.end();
835 ++iter) {
836 if (iter == ifBlocks_.begin()) {
837 stream << StringTools::indent(level) << "if ";
838 } else {
839 stream << StringTools::indent(level) << "end else if ";
840 }
841 iter->first.hdl(stream, lang);
842 stream << ") begin\n";
843 iter->second->hdl(stream, lang, level + 1);
844 }
845 if (elseBlock_ != nullptr) {
846 stream << StringTools::indent(level) << "end else begin\n";
847 elseBlock_->hdl(stream, lang, level + 1);
848 }
849 stream << StringTools::indent(level) << "end\n";
850 } else {
851 throw std::runtime_error(__PRETTY_FUNCTION__);
852 }
853 }
854
855 void build() override {
857 for (auto&& block : ifBlocks_) {
858 reads(block.first);
859 block.second->setParent(this);
860 block.second->build();
861 }
862 if (elseBlock_ != nullptr) {
863 elseBlock_->setParent(this);
864 elseBlock_->build();
865 }
866 }
867
868 private:
869 std::vector<std::pair<LHSValue,std::shared_ptr<SequentialStatement> > >
871 std::shared_ptr<SequentialStatement> elseBlock_;
872 };
873
874 /**
875 * Code block, i.e., a collection of concurrent statements
876 */
878 public:
879 CodeBlock() : SequentialStatement("codeBlock") {}
880
881 template<typename SS>
882 void append(SS cc) {
883 std::shared_ptr<SequentialStatement> ptr = std::make_shared<SS>(cc);
884 pushComponent(ptr);
885 }
886
887 void hdl(std::ostream& stream, Language lang, int level) override {
888 if (lang == Language::VHDL) {
889 implementAll(stream, lang, level);
890 } else if (lang == Language::Verilog) {
891 implementAll(stream, lang, level);
892 } else {
893 throw std::runtime_error(__PRETTY_FUNCTION__);
894 }
895 }
896 };
897
898 /**
899 * Async process/always.
900 */
901 class Asynchronous : public Generatable {
902 public:
903
904 Asynchronous(const std::string& name) : Generatable(name) {}
905
906 template<typename SS>
908 std::shared_ptr<SequentialStatement> ptr = std::make_shared<SS>(op);
909 pushComponent(ptr);
910 return *this;
911 }
912
913 template<typename Var>
914 void addVariable(Var op) {
915 std::shared_ptr<Variable> ptr = std::make_shared<Var>(op);
916 variables_.push_back(ptr);
917 }
918
919 virtual void reads(const std::string& var) override {
920 readList_.emplace(var);
921 if (parent() != nullptr) {
922 parent()->reads(var);
923 }
924 }
925
926 virtual void build() override; // implemented @EOF
927
928 virtual void
929 hdl(std::ostream& stream, Language lang, int level) override {
930 if (lang == Language::VHDL) {
931 stream << "\n";
932 stream << StringTools::indent(level) << name() << " : process(";
933 std::string separator = "";
934 for (auto&& r : readList_) {
935 if (!isConstant(r)) {
936 stream << separator << r;
937 separator = ", ";
938 }
939 }
940 stream << ")\n";
941 for (auto&& v : variables_) {
942 v->declare(stream, lang, level + 1);
943 }
944 stream << StringTools::indent(level) << "begin\n";
945 implementAll(stream, lang, level + 1);
946 stream << StringTools::indent(level) << "end process "
947 << name() << ";\n";
948 } else if (lang == Language::Verilog) {
949 stream << "\n";
950 stream << StringTools::indent(level) << "// " << name() << "\n";
951 stream << StringTools::indent(level) << "always @*";
952 /**
953 * @lassetodo Sensitivity list implementation here
954 * for verilog if needed.
955 * <pre>
956 * If sensitivity list is needed for verilog replace
957 * @* with @(, uncomment following code, and add ) before
958 * begin
959 *
960 * std::string separator = "";
961 * for (auto&& r : readList_) {
962 * stream << separator << r;
963 * separator = " or ";
964 * }
965 * </pre>
966 */
967 stream << " begin\n";
968 implementAll(stream, lang, level + 1);
969 stream << StringTools::indent(level) << "end\n";
970 } else {
971 throw std::runtime_error(__PRETTY_FUNCTION__);
972 }
973 }
974
975 private:
976 std::vector< std::shared_ptr<Variable> > variables_;
977 std::unordered_set<std::string> readList_;
978 };
979
980 /**
981 * Sync process/always.
982 */
983 class Synchronous : public Generatable {
984 public:
985 Synchronous(std::string name) : Generatable(name) {}
986
987 template<typename SS>
989 std::shared_ptr<SequentialStatement> ptr = std::make_shared<SS>(op);
990 pushComponent(ptr);
991 return *this;
992 }
993
994 template<typename Var>
995 void addVariable(Var op) {
996 std::shared_ptr<Variable> ptr = std::make_shared<Var>(op);
997 variables_.push_back(op);
998 }
999
1000 virtual void build() override; // implemented @EOF
1001
1002 virtual void writes(const std::string& var) override {
1003 //Generatable::writes(var);
1004 if (isVariable(var)) {
1005 return;
1006 }
1007 if (!isRegister(var)) {
1008 std::cerr << "Trying to write nonregister " << var << "\n";
1009 throw std::runtime_error(__PRETTY_FUNCTION__);
1010 }
1011 registers_.emplace(var);
1012 }
1013
1014 virtual void vhdlReset(std::ostream& stream, Language lang, int level) {
1015 if (hasOption("active low reset"))
1016 stream << StringTools::indent(level) << "if rstx = '0' then\n";
1017 if (hasOption("active high reset"))
1018 stream << StringTools::indent(level) << "if rst = '1' then\n";
1019 for (auto&& r : registers_) {
1020 Register& reg = getRegister(r);
1021 if (reg.resetOption() == ResetOption::Mandatory ||
1022 hasOption("reset everything")) {
1023 reg.reset(stream, lang, level + 1);
1024 }
1025 }
1026 // Leaves if clause open for else/elsif
1027 }
1028
1029 virtual void
1030 hdl(std::ostream& stream, Language lang, int level) override {
1031 if (lang == Language::VHDL) {
1032 stream << "\n"
1033 << StringTools::indent(level) << name() << " : process";
1034 if (hasOption("asynchronous reset")) {
1035 stream << "(clk, rstx)\n";
1036 } else {
1037 stream << "(clk)\n";
1038 }
1039
1040 for (auto&& v : variables_) {
1041 v->declare(stream, lang, level + 1);
1042 }
1043
1044 stream << StringTools::indent(level) << "begin\n";
1045 if (hasOption("asynchronous reset")) {
1046 vhdlReset(stream, lang, level + 1);
1047 stream << StringTools::indent(level + 1)
1048 << "elsif clk = '1' and clk'event then\n";
1049 implementAll(stream, lang, level + 2);
1050 } else {
1051 stream << StringTools::indent(level + 1)
1052 << "if clk = '1' and clk'event then\n";
1053 vhdlReset(stream, lang, level + 2);
1054 stream << StringTools::indent(level + 2) << "else\n";
1055 implementAll(stream, lang, level + 3);
1056 stream << StringTools::indent(level + 2) << "end if;\n";
1057 }
1058 stream << StringTools::indent(level + 1) << "end if;\n";
1059 stream << StringTools::indent(level)
1060 << "end process " << name() << ";\n";
1061 } else if (lang == Language::Verilog) {
1062 stream << "\n";
1063 stream << StringTools::indent(level) << "// " << name() << "\n";
1064 if (hasOption("asynchronous reset")) {
1065 stream << StringTools::indent(level)
1066 << "always @(posedge clk or negedge rstx) begin\n";
1067 } else {
1068 stream << StringTools::indent(level)
1069 << "always @(posedge clk) begin\n";
1070 }
1071 stream << StringTools::indent(level + 1)
1072 << "if (~rstx) begin\n";
1073 for (auto&& r : registers_) {
1074 Register& reg = getRegister(r);
1075 if (reg.resetOption() == ResetOption::Mandatory ||
1076 hasOption("reset everything")) {
1077 reg.reset(stream, lang, level + 2);
1078 }
1079 }
1080 stream << StringTools::indent(level + 1) << "end else begin\n";
1081 implementAll(stream, lang, level + 2);
1082 stream << StringTools::indent(level + 1) << "end\n";
1083 stream << StringTools::indent(level) << "end\n";
1084 } else {
1085 throw std::runtime_error(__PRETTY_FUNCTION__);
1086 }
1087 }
1088
1089 private:
1090 std::vector< std::shared_ptr<Variable> > variables_;
1091 std::unordered_set<std::string> registers_;
1092 };
1093
1094 /**
1095 * Force newline to hdl.
1096 */
1097 class NewLine : public Generatable {
1098 public:
1100
1101 void hdl(std::ostream& stream, Language lang, int level) final {
1102 (void)lang;
1103 (void)level;
1104 stream << "\n";
1105 }
1106 };
1107
1108 /**
1109 * Wrapper for behavioral code constructs.
1110 */
1111 class Behaviour : public Generatable {
1112 public:
1113 Behaviour() : Generatable("behaviour") {}
1114 virtual ~Behaviour() = default;
1115
1117 addComponent(std::forward<Synchronous>(rhs));
1118 return *this;
1119 }
1120
1122 addComponent(std::forward<Asynchronous>(rhs));
1123 return *this;
1124 }
1125
1127 addComponent(rhs);
1128 return *this;
1129 }
1130
1132 addComponent(rhs);
1133 return *this;
1134 }
1135
1137 addComponent(rhs);
1138 return *this;
1139 }
1140
1142 addComponent(assignment);
1143 return *this;
1144 }
1145
1146 Behaviour& operator<<(Assign&& assignment) {
1147 addComponent(assignment);
1148 return *this;
1149 }
1150
1151 void behaviour(std::ostream& stream, Language lang,
1152 int level) {
1153 forAll([&](std::shared_ptr<Generatable> c) {
1154 c->hdl(stream, lang, level);
1155 });
1156 }
1157
1158 private:
1159 };
1160
1161 /**
1162 * Entity/module.
1163 */
1164 class Module : public Generatable {
1165 public:
1167 set_header();
1168 }
1169
1171 prefix_(info.name) {
1172 set_header();
1173 id_ = id;
1174 for (auto&& p : info.parameters) {
1175 parameters_.emplace_back(Parameter{p.name, p.value});
1176 }
1177 for (auto&& p : info.ports) {
1178 Direction dir = p.direction == "in" ?
1180 if (p.vector) {
1181 *this << Port(p.name, dir, p.left + "+1");
1182 } else {
1183 *this << Port(p.name, dir);
1184 }
1185 }
1186 }
1187
1188 void set_header() {
1189 auto now = std::chrono::system_clock::now();
1190 auto now_c = std::chrono::system_clock::to_time_t(now);
1191 char buffer[31];
1192 std::stringstream ss;
1194 "2023", "");
1195 std::vector<TCEString> licenseStrs = licenseStr.split("\n");
1196 for (unsigned int i = 0; i < licenseStrs.size(); i++) {
1197 headerComment_.emplace_back(licenseStrs.at(i));
1198 }
1199 std::strftime(buffer, 30, "%c", std::localtime(&now_c));
1200 ss << buffer; // std::put_time(std::localtime(&now_c), "%c");
1201 headerComment_.emplace_back("");
1202 headerComment_.emplace_back(
1203 std::string("Generated on ") + ss.str());
1204 headerComment_.emplace_back("");
1205 }
1206
1207 void set_prefix(std::string prefix) {
1208 prefix_ = prefix;
1209 }
1210
1212 behaviours_.emplace_back(new Behaviour(rhs));
1213 return *this;
1214 }
1215
1217 behaviours_.emplace_back(new Behaviour(rhs));
1218 return *this;
1219 }
1220
1222 ports_.push_back(port);
1223 return *this;
1224 }
1225
1227 parameters_.emplace_back(param);
1228 return *this;
1229 }
1230
1232 constants_.emplace_back(constant);
1233 return *this;
1234 }
1235
1237 binaryConstants_.emplace_back(constant);
1238 return *this;
1239 }
1240
1242 wires_.emplace_back(new Wire(wire));
1243 return *this;
1244 }
1245
1247 registers_.emplace_back(reg);
1248 return *this;
1249 }
1250
1252 registers_.emplace_back(reg);
1253 return *this;
1254 }
1255
1257 options_.emplace(opt.name());
1258 return *this;
1259 }
1260
1262 modules_.emplace_back(rhs);
1263 return *this;
1264 }
1265
1267 modules_.emplace_back(rhs);
1268 return *this;
1269 }
1270
1271 void build() final {
1272 for (auto&& b : behaviours_) {
1273 b->setParent(this);
1274 b->build();
1275 }
1276 }
1277
1278 void appendToHeader(const std::string& line) {
1279 headerComment_.emplace_back(line);
1280 }
1281
1282 virtual bool isRegister(const std::string& name) final {
1283 for (auto&& r : registers_) {
1284 if (r.name() == name) {
1285 return true;
1286 }
1287 }
1288 return false;
1289 }
1290
1291 virtual bool isConstant(const std::string& name) final {
1292 for (auto&& r : constants_) {
1293 if (r.name() == name) {
1294 return true;
1295 }
1296 }
1297 for (auto&& r : binaryConstants_) {
1298 if (r.name() == name) {
1299 return true;
1300 }
1301 }
1302 return false;
1303 }
1304
1305 virtual bool isVariable(const std::string& name) final {
1306 for (auto&& v : variables_) {
1307 if (v->name() == name) {
1308 return true;
1309 }
1310 }
1311 return false;
1312 }
1313
1314 void registerVariable(const std::shared_ptr<Variable> var) {
1315 for (auto&& v : variables_) {
1316 if (v->name() == var->name()) {
1317 throw std::runtime_error("tried to register variable " +
1318 var->name() + " multiple times");
1319 }
1320 }
1321 variables_.push_back(var);
1322 }
1323
1324 Width width(const std::string& name) final {
1325 for (auto&& v : parameters_) {
1326 if (v.name() == name) {
1327 return v.width();
1328 }
1329 }
1330 for (auto&& v : constants_) {
1331 if (v.name() == name) {
1332 return v.width();
1333 }
1334 }
1335 for (auto&& v : registers_) {
1336 if (v.name() == name) {
1337 return v.width();
1338 }
1339 }
1340 for (auto&& v : wires_) {
1341 if (v->name() == name) {
1342 return v->width();
1343 }
1344 }
1345 for (auto&& v : variables_) {
1346 if (v->name() == name) {
1347 return v->width();
1348 }
1349 }
1350 for (auto&& v : ports_) {
1351 if (v.name() == name) {
1352 return v.width();
1353 }
1354 }
1355 // not finding a thing is an error.
1356 throw std::runtime_error("Couldn't find width for " + name);
1357 }
1358
1359 WireType wireType(const std::string& name) final {
1360 for (auto&& v : ports_) {
1361 if (v.name() == name) {
1362 return v.wireType();
1363 }
1364 }
1365 for (auto&& v : wires_) {
1366 if (v->name() == name) {
1367 return v->wireType();
1368 }
1369 }
1370 for (auto&& v : variables_) {
1371 if (v->name() == name) {
1372 return v->wireType();
1373 }
1374 }
1375 // not finding a thing is an error.
1376 throw std::runtime_error("Couldn't find wire type for " + name);
1377 }
1378
1379 void reads(const std::string& var) final { (void)var; }
1380
1381 void writes(const std::string& var) final { (void)var; }
1382
1383 void declare(std::ostream& stream, Language lang, int level) {
1384 if (lang == Language::VHDL) {
1385 stream << StringTools::indent(level) << "component "
1386 << name() << " is\n";
1387 // - Generics
1388 if (!parameters_.empty()) {
1389 std::string separator = "";
1390 stream << StringTools::indent(level + 1) << "generic (\n";
1391 for (auto&& parameter : parameters_) {
1392 stream << separator << StringTools::indent(level + 2);
1393 parameter.declare(stream, lang);
1394 separator = ";\n";
1395 }
1396 stream << ");\n";
1397 }
1398 // - Ports
1399 if (!ports_.empty()) {
1400 std::string separator = "";
1401 stream << StringTools::indent(level + 1) << "port (\n";
1402 for (auto&& port : ports_) {
1403 stream << separator << StringTools::indent(level + 2);
1404 port.declare(stream, lang);
1405 separator = ";\n";
1406 }
1407 stream << ");\n";
1408 }
1409 stream << StringTools::indent(level) << "end component "
1410 << name() << ";\n";
1411 } else if (lang == Language::Verilog) {
1412 // no declaration for verilog.
1413 } else {
1414 throw std::runtime_error(__PRETTY_FUNCTION__);
1415 }
1416 }
1417
1418 void instantiate(std::ostream& stream, Language lang, int level) {
1419 std::string instance = prefix_ + "_" + std::to_string(id_);
1420 if (lang == Language::VHDL) {
1421 stream << StringTools::indent(level)
1422 << instance << " : " << name() << "\n";
1423 if (parameters_.size() > 0) {
1424 stream << StringTools::indent(level + 1) << "generic map (\n";
1425
1426 std::string separator = "";
1427 for (auto&& p : parameters_) {
1428 stream << separator
1429 << StringTools::indent(level + 2)
1430 << p.name() << " => " << p.strValue();
1431 separator = ",\n";
1432 }
1433 stream << ")\n";
1434 }
1435 std::string separator = "";
1436 stream << StringTools::indent(level + 1) << "port map (\n";
1437 for (auto&& p : ports_) {
1438 stream << separator << StringTools::indent(level + 2)
1439 << p.name() << " => ";
1440 if (p.name() == "clk" || p.name() == "rstx" ||
1441 p.name() == "glock_in") {
1442 stream << p.name();
1443 } else {
1444 stream << instance << "_" << p.name();
1445 }
1446 separator = ",\n";
1447 }
1448 stream << ");\n";
1449 } else if (lang == Language::Verilog) {
1450 stream << StringTools::indent(level) << name() << " ";
1451 if (parameters_.size() > 0) {
1452 stream << "#(";
1453 std::string separator = "";
1454 for (auto&& p : parameters_) {
1455 stream << separator;
1456 stream << "." << p.name() << "(" << p.strValue() << ")";
1457 separator = ", ";
1458 }
1459 stream << ") ";
1460 }
1461 std::string separator = "";
1462 stream << instance << " (\n";
1463 for (auto&& p : ports_) {
1464 stream << separator;
1465 stream << StringTools::indent(level + 2) << "." << p.name()
1466 << "(";
1467 if (p.name() == "clk" || p.name() == "rstx" ||
1468 p.name() == "glock_in") {
1469 stream << p.name() << ")";
1470 } else {
1471 stream << instance << "_" << name() << ")";
1472 }
1473 separator = ",\n";
1474 }
1475 stream << ");\n";
1476 } else {
1477 throw std::runtime_error(__PRETTY_FUNCTION__);
1478 }
1479 }
1480
1481 void implement(std::ostream& stream, Language lang, int level = 0) {
1482 clear();
1483 build();
1484 if (lang == Language::VHDL) {
1485 std::string ident = StringTools::indent(level);
1486 // Header comment
1487 for (auto&& line : headerComment_) {
1488 stream << ident << "-- " << line << "\n";
1489 }
1490 // Libraries
1491 stream << ident << "\n"
1492 << ident << "library ieee;\n"
1493 << ident << "use ieee.std_logic_1164.all;\n"
1494 << ident << "use ieee.numeric_std.all;\n"
1495 << ident << "use ieee.std_logic_misc.all;\n"
1496 // Entity
1497 << ident << "\n"
1498 << ident << "entity " << name() << " is\n";
1499 // - Generics
1500 if (!parameters_.empty()) {
1501 std::string separator = "";
1502 stream << StringTools::indent(level + 1) << "generic (\n";
1503 for (auto&& parameter : parameters_) {
1504 stream << separator;
1505 parameter.declare(stream, lang, level + 2);
1506 separator = ";\n";
1507 }
1508 stream << ");\n";
1509 }
1510 // - Ports
1511 if (!ports_.empty()) {
1512 std::string separator = "";
1513 stream << StringTools::indent(level + 1) << "port (\n";
1514 for (auto&& port : ports_) {
1515 stream << separator;
1516 port.declare(stream, lang, level + 2);
1517 separator = ";\n";
1518 }
1519 stream << ");\n";
1520 }
1521 stream << ident << "end entity " << name() << ";\n"
1522 // Architecture
1523 << ident << "\n"
1524 << ident << "architecture rtl of "
1525 << name() << " is\n";
1526 // constants
1527 if (!constants_.empty() || !binaryConstants_.empty()) {
1528 stream << "\n";
1529 }
1530 for (auto&& c : constants_) {
1531 c.declare(stream, lang, level + 1);
1532 }
1533 for (auto&& c : binaryConstants_) {
1534 c.declare(stream, lang, level + 1);
1535 }
1536 // wires
1537 if (!wires_.empty()) {
1538 stream << "\n";
1539 }
1540 for (auto&& w : wires_) {
1541 w->declare(stream, lang, level + 1);
1542 }
1543 // registers
1544 if (!registers_.empty()) {
1545 stream << "\n";
1546 }
1547 for (auto&& r : registers_) {
1548 r.declare(stream, lang, level + 1);
1549 }
1550 // declare components
1551 std::vector<std::string> declared;
1552 for (auto&& m : modules_) {
1553 if (std::find(declared.begin(), declared.end(),
1554 m.name()) != declared.end()) {
1555 continue;
1556 }
1557 stream << "\n";
1558 m.declare(stream, lang, level + 1);
1559 declared.emplace_back(m.name());
1560 }
1561 stream << StringTools::indent(level) << "\nbegin\n\n";
1562 // instantiate components
1563 for (auto&& m : modules_) {
1564 m.instantiate(stream, lang, level + 1);
1565 stream << "\n";
1566 }
1567 // actual behavioural code
1568 for (auto&& b : behaviours_) {
1569 b->behaviour(stream, lang, level + 1);
1570 }
1571 stream << "\n";
1572 stream << StringTools::indent(level)
1573 << "end architecture rtl;\n\n";
1574
1575 } else if (lang == Language::Verilog) {
1576 // Header comment
1577 stream << StringTools::indent(level) << "/*\n";
1578 for (auto&& line : headerComment_) {
1579 stream << StringTools::indent(level)
1580 << " * " << line << "\n";
1581 }
1582 stream << StringTools::indent(level) << " */\n";
1583 // Module
1584 stream << StringTools::indent(level) << "\n";
1585 stream << StringTools::indent(level) << "module " << name();
1586 // - Parameters
1587 if (!parameters_.empty()) {
1588 std::string separator = "";
1589 stream << " #(\n";
1590 for (auto&& parameter : parameters_) {
1591 stream << separator;
1592 parameter.declare(stream, lang, level + 2);
1593 separator = ",\n";
1594 }
1595 stream << ")";
1596 }
1597 // - Ports
1598 if (!ports_.empty()) {
1599 std::string separator = "";
1600 stream << " (\n";
1601 for (auto&& port : ports_) {
1602 stream << separator;
1603 port.declare(stream, lang, level + 2);
1604 separator = ",\n";
1605 }
1606 stream << ")";
1607 }
1608 // end module interface
1609 stream << ";\n";
1610 // constants
1611 if (!constants_.empty() || !binaryConstants_.empty()) {
1612 stream << "\n";
1613 }
1614 for (auto&& c : constants_) {
1615 c.declare(stream, lang, level + 1);
1616 }
1617 for (auto&& c : binaryConstants_) {
1618 c.declare(stream, lang, level + 1);
1619 }
1620 // wires
1621 if (!wires_.empty()) {
1622 stream << "\n";
1623 }
1624 for (auto&& w : wires_) {
1625 w->declare(stream, lang, level + 1);
1626 }
1627 // variables
1628 if (!variables_.empty()) {
1629 stream << "\n";
1630 for (auto&& v : variables_) {
1631 v->declare(stream, lang, level + 1);
1632 }
1633 }
1634 // registers
1635 if (!registers_.empty()) {
1636 stream << "\n";
1637 }
1638 for (auto&& r : registers_) {
1639 r.declare(stream, lang, level + 1);
1640 }
1641 // instantiate stuff
1642 for (auto&& m : modules_) {
1643 stream << "\n";
1644 m.instantiate(stream, lang, level + 1);
1645 }
1646 // actual code
1647 stream << "\n";
1648 for (auto&& b : behaviours_) {
1649 b->behaviour(stream, lang, level + 1);
1650 }
1651 // end module
1652 stream << "\n";
1653 stream << StringTools::indent(level) << "endmodule\n\n";
1654 } else {
1655 throw std::runtime_error(__PRETTY_FUNCTION__);
1656 }
1657 }
1658
1659 bool hasOption(const std::string& var) final {
1660 return std::find(options_.begin(), options_.end(), var) !=
1661 options_.end();
1662 }
1663
1664 Register& getRegister(const std::string& var) final {
1665 for (auto&& r : registers_) {
1666 if (r.name() == var) {
1667 return r;
1668 }
1669 }
1670 throw std::runtime_error("Couldn't find register '" + var + "'");
1671 }
1672
1673 private:
1674 void clear() {
1675 // clear variables.
1676 variables_.clear();
1677 // Remove duplicate registers.
1678 registers_.erase(std::unique(registers_.begin(), registers_.end(),
1679 [](Register l, Register r) {
1680 return l.name() == r.name();
1681 }),
1682 registers_.end());
1683 }
1684 int id_ = 0;
1685 std::string prefix_;
1686 std::unordered_set<std::string> options_;
1687 std::vector<std::string> headerComment_;
1688 std::vector<Parameter> parameters_;
1689 std::vector<Port> ports_;
1690 std::vector<IntegerConstant> constants_;
1691 std::vector<BinaryConstant> binaryConstants_;
1692 std::vector<std::shared_ptr<Wire>> wires_;
1693 std::vector<Register> registers_;
1694 std::vector<std::shared_ptr<Variable> > variables_;
1695 std::vector<std::shared_ptr<Behaviour>> behaviours_;
1696 std::vector<Module> modules_;
1697 };
1698}
find Finds info of the inner loops in the false
Assign(std::string var, LHSValue value, int idx)
void build() override
Assign(std::string var, LHSValue value)
Assign(std::string var, LHSValue value, int ub, int lb)
void hdl(std::ostream &stream, Language lang, int level) override
Asynchronous(const std::string &name)
virtual void hdl(std::ostream &stream, Language lang, int level) override
virtual void build() override
std::vector< std::shared_ptr< Variable > > variables_
std::unordered_set< std::string > readList_
virtual void reads(const std::string &var) override
Asynchronous & operator<<(SS op)
Behaviour & operator<<(Asynchronous &rhs)
virtual ~Behaviour()=default
void behaviour(std::ostream &stream, Language lang, int level)
Behaviour & operator<<(Synchronous &rhs)
Behaviour & operator<<(Assign &&assignment)
Behaviour & operator<<(Assign &assignment)
Behaviour & operator<<(NewLine &&rhs)
Behaviour & operator<<(NewLine &rhs)
Behaviour & operator<<(Synchronous &&rhs)
int value() const noexcept
void declare(std::ostream &stream, Language lang, int level)
BinaryConstant(std::string name, int width, int value)
Case & operator<<(SS op)
void hdl(std::ostream &stream, Language lang, int level) override
Case & operator<<(BinaryLiteral &rhs)
Case & operator<<(std::string &rhs)
std::vector< int > intCases_
Case(std::string stringCase)
std::string stringCase_
std::vector< BinaryLiteral > binaryCases_
Case & operator<<(int rhs)
Case & operator<<(BinaryLiteral &&rhs)
Case & operator<<(std::string &&rhs)
void hdl(std::ostream &stream, Language lang, int level) override
DefaultAssign(std::string name)
DefaultAssign(std::string name, std::string value)
void hdl(std::ostream &stream, Language lang, int level) override
DefaultCase & operator<<(DefaultAssign &rhs)
DefaultCase & operator<<(DefaultAssign &&rhs)
void hdl(std::ostream &stream, Language lang, int level) override
virtual void reads(const std::string &var)
virtual Register & getRegister(const std::string &var)
Generatable * parent() const noexcept
const std::string & name() const noexcept
virtual bool isConstant(const std::string &name)
virtual void implementAll(std::ostream &stream, Language lang)
virtual WireType wireType() const
virtual void writes(const std::string &var)
void pushComponent(std::shared_ptr< Generatable > c)
void addComponent(Component c)
virtual bool isRegister(const std::string &name)
virtual bool hasOption(const std::string &var)
virtual bool isVariable(const std::string &name)
std::deque< std::string > impl_
void hdl(std::ostream &stream, Language lang, int level) override
std::vector< std::string > readList_
HDLOperation(std::string name, std::deque< std::string > impl, Language lang)
HDLOperation & operator<<(const std::string &&rhs)
HDLOperation & operator<<(const std::string &rhs)
If(LHSValue cls, SS ifBlock)
virtual void hdl(std::ostream &stream, Language lang, int level) override
void elseIfClause(LHSValue cls, SS ifBlock)
void elseClause(SS elseBlock)
std::shared_ptr< SequentialStatement > elseBlock_
void build() override
std::vector< std::pair< LHSValue, std::shared_ptr< SequentialStatement > > > ifBlocks_
IntegerConstant(std::string name, int value)
int value() const noexcept
void declare(std::ostream &stream, Language lang, int level)
void hdl(std::ostream &stream, Language lang, int level)
Definition LHSValue.cc:37
LogicVariable(std::string name, int width=1)
LogicVariable(std::string name, std::string width)
WireType wireType(const std::string &name) final
void implement(std::ostream &stream, Language lang, int level=0)
Module(ipxact::ModuleInfo info, int id)
Module & operator<<(Module &&rhs)
virtual bool isRegister(const std::string &name) final
Width width(const std::string &name) final
Register & getRegister(const std::string &var) final
std::vector< std::shared_ptr< Variable > > variables_
Module & operator<<(Behaviour &&rhs)
Module & operator<<(Wire &&wire)
Module & operator<<(Register &&reg)
std::vector< Module > modules_
void declare(std::ostream &stream, Language lang, int level)
Module & operator<<(Port &&port)
void appendToHeader(const std::string &line)
Module(std::string name)
Module & operator<<(Option &&opt)
bool hasOption(const std::string &var) final
Module & operator<<(IntegerConstant &&constant)
std::vector< std::shared_ptr< Behaviour > > behaviours_
std::unordered_set< std::string > options_
Module & operator<<(BinaryConstant &&constant)
std::vector< BinaryConstant > binaryConstants_
Module & operator<<(Module &rhs)
void set_prefix(std::string prefix)
std::vector< Register > registers_
void writes(const std::string &var) final
void instantiate(std::ostream &stream, Language lang, int level)
Module & operator<<(Behaviour &rhs)
void reads(const std::string &var) final
Module & operator<<(Parameter &&param)
std::vector< IntegerConstant > constants_
virtual bool isConstant(const std::string &name) final
virtual bool isVariable(const std::string &name) final
std::vector< std::shared_ptr< Wire > > wires_
std::vector< Parameter > parameters_
std::vector< std::string > headerComment_
void registerVariable(const std::shared_ptr< Variable > var)
std::vector< Port > ports_
Module & operator<<(Register &reg)
void hdl(std::ostream &stream, Language lang, int level) final
Option(std::string name)
Parameter(std::string name, std::string value)
void declare(std::ostream &stream, Language lang, int level=0)
Parameter(std::string name, int value=-1)
void hdl(std::ostream &stream, Language lang, int level) final
RawCodeLine(std::string vhdl, std::string verilog)
void reset(std::ostream &stream, Language lang, int ident)
ResetOption resetOption() const noexcept
virtual void hdl(std::ostream &stream, Language lang, int level)
SignedVariable(std::string name, std::string width)
SignedVariable(std::string name, int width=1)
void addCase(DefaultCase rhs)
void build() override
void hdl(std::ostream &stream, Language lang, int level) override
void addCase(Case rhs)
Switch(LHSValue control)
virtual void build() override
std::unordered_set< std::string > registers_
Synchronous(std::string name)
virtual void hdl(std::ostream &stream, Language lang, int level) override
virtual void writes(const std::string &var) override
virtual void vhdlReset(std::ostream &stream, Language lang, int level)
Synchronous & operator<<(SS op)
std::vector< std::shared_ptr< Variable > > variables_
UnsignedVariable(std::string name, int width=1)
UnsignedVariable(std::string name, std::string width)
Variable(std::string name, int width=1)
std::string verilogRange()
void declare(std::ostream &stream, Language lang, int level)
virtual std::string vhdlTypeDeclaration()
std::string verilogTypeDeclaration()
Variable(std::string name, std::string width)
Wire(std::string name, std::string width)
std::string strWidth_
Width width() final
void declare(std::ostream &stream, Language lang, int ident)
Wire(std::string name, int width=1, WireType wt=WireType::Auto)
WireType wireType() const final
static std::string generateMITLicense(const std::string &year, const std::string &comment)
static std::string indent(int level)
std::vector< TCEString > split(const std::string &delim) const
Definition TCEString.cc:114
std::string strWidth
Definition HWGenTools.hh:38
std::vector< Parameter > parameters
Definition IPXact.hh:55
std::vector< Port > ports
Definition IPXact.hh:56