OpenASIP 2.2
Loading...
Searching...
No Matches
BaseNetlistBlock.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2015 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 BaseNetlistBlock.cc
26 *
27 * Implementation of BaseNetlistBlock class.
28 *
29 * Created on: 20.4.2015
30 * @author Henry Linjamäki 2015 (henry.linjamaki-no.spam-tut.fi)
31 * @note rating: red
32 */
33
34#include "BaseNetlistBlock.hh"
35
36#include <algorithm>
37#include <locale>
38
39#include "NetlistPort.hh"
40#include "NetlistPortGroup.hh"
41#include "Netlist.hh"
42#include "NetlistTools.hh"
43#include "Parameter.hh"
44#include "VHDLNetlistWriter.hh"
46
47#include "Application.hh"
48#include "ContainerTools.hh"
49#include "FileSystem.hh"
50
51namespace ProGe {
52
54 : parent_(nullptr),
55 subBlocks_(),
56 parameters_(),
57 ports_(),
58 portGroups_(),
59 netlist_(new Netlist()),
60 instanceName_("defaultInstanceName_inst0"),
61 moduleName_("defaultModuleName"),
62 packages_() {}
63
65 : parent_(parent),
66 subBlocks_(),
67 parameters_(),
68 ports_(),
69 portGroups_(),
70 netlist_(new Netlist()),
71 instanceName_("defaultInstanceName_inst0"),
72 moduleName_("defaultModuleName"),
73 packages_() {
74 if (parent_ != nullptr) {
75 parent_->addSubBlock(this);
76 }
77}
78
80 const std::string& moduleName, const std::string& instanceName,
81 BaseNetlistBlock* parent)
82 : parent_(parent),
83 subBlocks_(),
84 parameters_(),
85 ports_(),
86 portGroups_(),
87 netlist_(new Netlist()),
88 instanceName_(instanceName),
89 moduleName_(moduleName),
90 packages_() {
91 if (instanceName.empty()) {
92 setInstanceName(moduleName + "_inst0");
93 }
95 if (parent_ != nullptr) {
96 parent_->addSubBlock(this);
97 }
99
101 if (parent_ != nullptr) {
102 parent_->removeSubBlock(this);
103 parent_ = nullptr;
104 }
105
106 for (PortGroupContainerType::reverse_iterator it = portGroups_.rbegin();
107 it != portGroups_.rend();) {
108 NetlistPortGroup* toDeleted = *it;
109 it++;
110 portGroups_.pop_back();
111 delete toDeleted;
112 }
113
114 for (PortContainerType::reverse_iterator it = ports_.rbegin();
115 it != ports_.rend();) {
116 NetlistPort* toDeleted = *it;
117 it++;
118 ports_.pop_back();
119 delete toDeleted;
120 }
121
122 for (BlockContainerType::reverse_iterator it = subBlocks_.rbegin();
123 it != subBlocks_.rend();) {
124 BaseNetlistBlock* toDeleted = *it;
125 it++;
126 subBlocks_.pop_back();
127 delete toDeleted;
128 }
129
130 delete netlist_;
131 netlist_ = nullptr;
132}
133
134const std::string&
138
139const std::string&
142}
143
144const std::string
146 return instanceName_ + " : " + moduleName();
147}
148
149size_t
151 return subBlocks_.size();
154const BaseNetlistBlock&
155BaseNetlistBlock::subBlock(size_t index) const {
156 return *subBlocks_.at(index);
158
159bool
160BaseNetlistBlock::hasSubBlock(const std::string& instanceName) const {
161 for (size_t i = 0; i < subBlockCount(); i++) {
163 return true;
164 }
165 }
166 return false;
167}
168
169/**
170 * Returns true if the given netlist block is sub block of this block.
171 */
172bool
176
179 return *subBlocks_.at(index);
180}
181
182bool
183BaseNetlistBlock::hasParameter(const std::string& name) const {
184 for (size_t i = 0; i < parameterCount(); i++) {
185 if (parameter(i).name() == name) {
186 return true;
187 }
188 }
189 return false;
190}
191
192/**
193 * Returns a Parameter object by name.
194 *
195 * @exception NotAvailable Thrown if the block does not have such Parameter.
196 */
197const Parameter&
198BaseNetlistBlock::parameter(const std::string& name) const {
199 for (size_t i = 0; i < parameterCount(); i++) {
200 if (parameter(i).name() == name) {
201 return parameter(i);
202 }
203 }
204
205 throw NotAvailable(
206 __FILE__, __LINE__, __func__,
207 std::string("The block (") + instanceName() + ":" + moduleName() +
208 ") does not have parameter \"" + name + "\"");
209}
210
211/**
212 * Returns a Parameter object by name.
213 *
214 * @exception NotAvailable Thrown if the block does not have such Parameter.
215 */
217BaseNetlistBlock::parameter(const std::string& name) {
218 for (size_t i = 0; i < parameterCount(); i++) {
219 if (parameters_.at(i).name() == name) {
220 return parameters_.at(i);
221 }
222 }
223
224 throw NotAvailable(
225 __FILE__, __LINE__, __func__,
226 std::string("The block (") + instanceName() + ":" + moduleName() +
227 ") does not have parameter \"" + name + "\"");
228}
229
230size_t
232 return parameters_.size();
233}
234
235const Parameter&
236BaseNetlistBlock::parameter(size_t index) const {
237 if (index >= parameterCount()) {
238 throw OutOfRange(__FILE__, __LINE__, __func__);
239 }
240
241 return parameters_.at(index);
242}
243
244/**
245 * Return port count in this block including ports from netlist port groups.
246 */
247size_t
249 return ports_.size();
250}
251
252const NetlistPort&
253BaseNetlistBlock::port(size_t index) const {
254 return *ports_.at(index);
255}
256
257/**
258 * Returns list of ports by Signal Type.
259 *
260 * @param The list of ports by matching signal type in insertion order.
261 *
262 */
263std::vector<const NetlistPort*>
265 std::vector<const NetlistPort*> result;
266 for (size_t i = 0; i < portCount(); i++) {
267 const NetlistPort& port = this->port(i);
268 if (port.assignedSignal().type() == type) {
269 result.push_back(&port);
270 }
271 }
272 return result;
273}
274
275/**
276 * Returns a port by Signal Type at given index.
277 *
278 *
279 * @param The list of ports by matching signal type at the index.
280 * @exception OutOfRange If the index is the number of found matches or
281 * larger.
282 */
283const NetlistPort&
284BaseNetlistBlock::portBy(SignalType type, size_t index) const {
285 std::vector<const NetlistPort*> matches = portsBy(type);
286 if (index < matches.size()) {
287 return *matches.at(index);
288 } else {
291 "No port by signal at index " + Conversion::toString(index));
292 }
293}
294
295/**
296 * Return true if the netlist block has at least one port by given Signal
297 * Type.
298 */
299bool
301 std::vector<const NetlistPort*> result;
302 for (size_t i = 0; i < portCount(); i++) {
303 const NetlistPort& port = this->port(i);
304 if (port.assignedSignal().type() == type) {
305 return true;
306 }
307 }
308 return false;
309}
310
311/**
312 * Returns a port that matches (partially) the given name.
313 *
314 * @return The matching port. If not found, returns nullptr.
315 */
316const NetlistPort*
317BaseNetlistBlock::port(const std::string& portName, bool partialMatch) const {
318 return findPort(portName, false, partialMatch);
319}
320
323 return *ports_.at(index);
324}
325
326size_t
328 return portGroups_.size();
329}
330
331const NetlistPortGroup&
332BaseNetlistBlock::portGroup(size_t index) const {
333 return *portGroups_.at(index);
334}
335
336std::vector<const NetlistPortGroup*>
338 std::vector<const NetlistPortGroup*> found;
339 for (size_t i = 0; i < portGroupCount(); i++) {
340 if (portGroup(i).assignedSignalGroup() == type) {
341 found.push_back(&portGroup(i));
342 }
343 }
344 return found;
345}
346
347const Netlist&
349 return *netlist_;
350}
351
352bool
354 return parent_ != nullptr;
355}
356
357const BaseNetlistBlock&
360 return *parent_;
361}
362
368
369/**
370 * Replaces the instance name of the block.
371 *
372 * The new name must be unique within sub blocks of parent block it is
373 * attached to.
374 *
375 * @exception ObjectAlreadyExists Thrown if the name is not unique.
376 *
377 */
378void
379BaseNetlistBlock::setInstanceName(const std::string& name) {
382 ObjectAlreadyExists, "New instance name of " + name +
383 " is not unique within parent "
384 "block of " +
385 parentBlock().instanceName() + " : " +
387 }
389}
390
391void
392BaseNetlistBlock::setModuleName(const std::string& name) {
394}
395
396/**
397 * Adds sub block to this block and acquires ownership of it.
398 *
399 * @param subBlock The block to be added.
400 * @param instanceName The instance base name to be given for sub block. If
401 * the given or sub block's instance name is not unique within the block The
402 * name will be prefixed with a running number.
403 */
404void
406 BaseNetlistBlock* subBlock, const std::string& instanceName) {
407 if (!instanceName.empty()) {
410 } else {
411 if (subBlock->instanceName().empty()) {
413 *this, subBlock->moduleName() + "_inst0"));
414 } else {
416 *this, subBlock->instanceName()));
417 }
418 }
419
421 subBlock->setParent(this);
422 subBlocks_.push_back(subBlock);
423
424 // Register ports of the subblock so connections can be made.
425 for (size_t i = 0; i < subBlock->portCount(); i++) {
427 }
428}
429
430/**
431 * Deletes given sub block and its all sub blocks.
432 */
433void
435 // todo remove port descriptions of deleted block in the netlist.
436 for (size_t i = 0; i < subBlocks_.size(); i++) {
437 if (subBlocks_.at(i) == subBlock) {
438 BaseNetlistBlock* toDeleted = subBlocks_.at(i);
440 delete toDeleted;
441 }
442 }
443}
444
445/**
446 * Removes sub block from this block and does not delete it.
447 */
448void
450 // todo remove port descriptions of removed block in the netlist.
451 for (size_t i = 0; i < subBlocks_.size(); i++) {
452 if (subBlocks_.at(i) == subBlock) {
454 }
455 }
456}
457
458/**
459 * Adds port to this block and acquires ownership of it.
460 *
461 * Added port will point to this block after the call.
462 *
463 * @exception ObjectAlreadyExists Thrown if the netlist block already has a
464 * port by same name.
465 */
468 assert(port != nullptr && "Attempted to add null port.");
469 if (findPort(port->name(), false, false)) {
472 "Given port by name (" + port->name() +
473 ") already exists in the netlist block (" +
474 this->instanceName() + " : " + this->moduleName() + ").");
475 }
476
477 if (!port->hasParentBlock() || &port->parentBlock() != this) {
478 port->setParent(this);
479 }
480 ports_.push_back(port);
482 if (parent_ != nullptr) {
484 }
485 return port;
486}
487
488/**
489 * Removes the given port from the block.
490 *
491 * After call the port is parent block reference is set to nullptr.
492 */
493void
495 assert(
496 &port->parentBlock() == this &&
497 "Attempted to remove a port the block does not have.");
498
500 if (this->hasParentBlock()) {
502 }
504 port->setParent(nullptr);
505}
506
507void
509 portGroups_.push_back(portGroup);
510 portGroup->setParent(this);
511 for (size_t i = 0; i < portGroup->portCount(); i++) {
512 if (!netlist().isRegistered(portGroup->portAt(i))) {
514 }
515 }
516}
517
518void
520 for (size_t i = 0; i < portGroups_.size(); i++) {
521 if (portGroups_.at(i) == port) {
523 break;
524 }
525 }
526}
527
528/**
529 * Adds parameter to the block overwriting the existing one by name.
530 */
531void
533 for (Parameter& p : parameters_) {
534 if (p.name() == param.name()) {
535 p = param;
536 return;
537 }
538 }
539 parameters_.push_back(param);
540}
541
542/**
543 * Adds new parameter to the block. Throws exception if the block has the
544 * parameter by the name already.
545 */
546void
548 // Check for uniqueness //
549 for (Parameter& p : parameters_) {
550 if (p.name() == param.name()) {
552 __FILE__, __LINE__,
553 "The block \"" + name() + "\" already has parameter\"" +
554 param.name() + "\"");
555 }
556 }
557
558 // Check if parameter's value refers to a constant //
559 if (param.valueIsConstant()) {
560 std::string packageName = param.packageNameOfConstant();
561 assert(!packageName.empty());
562 addPackage(packageName);
563 }
564
565 parameters_.push_back(param);
566}
567
568/**
569 * Returns a port that matches (partially) the given name.
570 *
571 * If not found, returns nullptr
572 */
575 const std::string& portName, bool recursiveSearch,
576 bool partialMatch) const {
577 if (recursiveSearch) {
578 assert(
579 false &&
580 "BaseNetlistBlock::findPort(): "
581 "recursive search not implemented.");
582 }
583
584 NetlistPort* portPtr = nullptr;
585 for (size_t i = 0; i < portCount(); i++) {
586 if (ports_.at(i)->name() == portName) {
587 return ports_.at(i);
588 }
589 }
590 if (partialMatch) {
591 for (size_t i = 0; i < portCount(); i++) {
592 if (ports_.at(i)->name().find(portName) != std::string::npos) {
593 return ports_.at(i);
594 }
595 }
596 }
597
598 return portPtr;
599}
600
601void
603
604void
606
607void
609
610/**
611 * Does nothing on self but calls write function on each sub block.
612 */
613void
614BaseNetlistBlock::write(const Path& targetBaseDir, HDL targetLang) const {
615 // Call write of each sub block //
616 for (BaseNetlistBlock* subblock : subBlocks_) {
617 subblock->write(targetBaseDir, targetLang);
618 }
619}
620
621/**
622 * Writes HDL source of itself only using default netlist writer.
623 */
624void
625BaseNetlistBlock::writeSelf(const Path& targetBaseDir, HDL targetLang) const {
626 if (targetLang == HDL::VHDL) {
627 VHDLNetlistWriter(*this).write(targetBaseDir.string());
628 } else if (targetLang == HDL::Verilog) {
629 VerilogNetlistWriter(*this).write(targetBaseDir.string());
630 } else {
631 THROW_EXCEPTION(NotAvailable, "Given HDL language is not supported.");
632 }
633}
634
635/**
636 * Creates new netlist block that only includes without of its subblocks or
637 * interconnections.
638 */
640BaseNetlistBlock::shallowCopy(const std::string& instanceName) const {
642 this->moduleName(),
643 (!instanceName.empty()) ? instanceName : this->instanceName(),
644 nullptr);
645
646 for (size_t i = 0; i < this->parameterCount(); i++) {
647 block->setParameter(this->parameter(i));
648 }
649 for (size_t i = 0; i < netlist().parameterCount(); i++) {
650 block->netlist().setParameter(this->netlist().parameter(i));
651 }
652 std::map<std::string, NetlistPort*> copiedPorts;
653 // Copy ports while preserving their insertion order.
654 for (size_t i = 0; i < portCount(); i++) {
655 NetlistPort* copiedPort = nullptr;
656 copiedPort = BaseNetlistBlock::port(i).copyTo(*block);
657 copiedPorts.insert({{copiedPort->name(), copiedPort}});
658 }
659 for (size_t i = 0; i < portGroupCount(); i++) {
660 const NetlistPortGroup* portGrp = &portGroup(i);
661 // Cloning to copy original class type, but clear ports as they are
662 // already created and added to the new block.
663 NetlistPortGroup* newGroup = portGrp->clone();
664 newGroup->clear();
665 for (auto port : *portGrp) {
666 newGroup->addPort(*copiedPorts.at(port->name()));
667 }
668 block->addPortGroup(newGroup);
669 }
670 for (size_t i = 0; i < packageCount(); i++) {
671 block->addPackage(this->package(i));
672 }
673
674 assert(
675 block->portCount() == this->portCount() &&
676 "Port count mismatch in shallow copy.");
677 return block;
678}
679
680Netlist&
682 assert(netlist_ != nullptr);
683 return *netlist_;
684}
685
686void
687BaseNetlistBlock::addPackage(const std::string& packageName) {
688 if (!ContainerTools::containsValue(packages_, packageName)) {
689 packages_.push_back(packageName);
690 }
691}
692
693size_t
695 return packages_.size();
696}
697
698const std::string&
699BaseNetlistBlock::package(size_t idx) const {
700 return packages_.at(idx);
701}
702
703/**
704 * Changes parent block to given one.
705 */
706void
708 if (parent_ != nullptr && parent_ != newparent) {
709 BaseNetlistBlock* oldParent = parent_;
710 parent_ = nullptr; // Prevent parent block causing recursive call of
711 // setParent() when calling detachSubBlock().
712 oldParent->removeSubBlock(this);
713 }
714 parent_ = newparent;
715}
716
717/**
718 * Connects all unconnected clock ports of sub block to this block's clock
719 * port if there is one.
720 */
721void
723 auto clkPorts = this->portsBy(SignalType::CLOCK);
724 assert(clkPorts.size() == 1);
725 const NetlistPort& thisClk = *clkPorts.at(0);
726
727 for (size_t i = 0; i < subBlockCount(); i++) {
728 const BaseNetlistBlock& block = subBlock(i);
729 for (auto port : block.portsBy(SignalType::CLOCK)) {
730 if (!netlist().isPortConnected(*port) &&
731 thisClk.direction() == port->direction()) {
732 netlist().connect(thisClk, *port);
733 }
734 }
735 }
736}
737
738/**
739 * Connects all unconnected reset ports of sub block to this block's reset
740 * port if there is one.
741 */
742void
744 auto resetPorts = this->portsBy(SignalType::RESET);
745 assert(resetPorts.size() == 1);
746 const NetlistPort& thisReset = *resetPorts.at(0);
747
748 for (size_t i = 0; i < subBlockCount(); i++) {
749 const BaseNetlistBlock& block = subBlock(i);
750 for (auto port : block.portsBy(SignalType::RESET)) {
751 if (!netlist().isPortConnected(*port) &&
752 thisReset.direction() == port->direction()) {
753 netlist().connect(thisReset, *port);
754 }
755 }
756 }
757}
758
759} /* namespace ProGe */
#define __func__
#define assert(condition)
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)
static void swapRemoveValue(std::vector< E > &aContainer, I index)
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
static std::string toString(const T &source)
PortContainerType ports_
The ports of the block.
virtual const BaseNetlistBlock & subBlock(size_t index) const
virtual size_t parameterCount() const
std::string moduleName_
The module name of the block.
virtual bool hasParameter(const std::string &name) const
BlockContainerType subBlocks_
The sub blocks of this netlist block.
void setModuleName(const std::string &name)
virtual size_t subBlockCount() const
virtual size_t packageCount() const
void setInstanceName(const std::string &name)
virtual const Parameter & parameter(const std::string &name) const
void addSubBlock(BaseNetlistBlock *subBlock, const std::string &instanceName="")
NetlistPort * addPort(NetlistPort *port)
virtual size_t portGroupCount() const
void deleteSubBlock(BaseNetlistBlock *subBlock)
virtual const std::string & package(size_t idx) const
virtual bool hasSubBlock(const std::string &instanceName) const
PortGroupContainerType portGroups_
The ports of the block.
virtual std::vector< const NetlistPort * > portsBy(SignalType type) const
std::string instanceName_
The instance name of the block.
BaseNetlistBlock * shallowCopy(const std::string &instanceName="") const
virtual const NetlistPortGroup & portGroup(size_t index) const
void addParameter(const Parameter &param)
virtual void write(const Path &targetBaseDir, HDL targetLang=VHDL) const override
BaseNetlistBlock * parent_
The reference to parent block of this block.
virtual void build() override
virtual bool hasPortsBy(SignalType type) const
virtual bool isSubBlock(const BaseNetlistBlock &block) const
virtual const NetlistPort & portBy(SignalType type, size_t index=0) const
virtual const NetlistPort & port(size_t index) const
const std::string & instanceName() const
void removePortGroup(NetlistPortGroup *portGroup)
virtual bool hasParentBlock() const
virtual size_t portCount() const
virtual std::vector< const NetlistPortGroup * > portGroupsBy(SignalGroupType type) const
void removeSubBlock(BaseNetlistBlock *subBlock)
virtual void connect() override
Netlist * netlist_
The netlist of the block.
virtual const BaseNetlistBlock & parentBlock() const
ParameterContainerType parameters_
The parameters of the block.
const std::string & moduleName() const
void addPackage(const std::string &packageName)
const std::string name() const
virtual void writeSelf(const Path &targetBaseDir, HDL targetLang=VHDL) const
void addPortGroup(NetlistPortGroup *portGroup)
void setParameter(const Parameter &param)
virtual const Netlist & netlist() const
NetlistPort * findPort(const std::string &portName, bool recursiveSearch=false, bool partialMatch=true) const
void removePort(NetlistPort *port)
virtual void finalize() override
virtual void setParent(BaseNetlistBlock *parent)
std::vector< std::string > packages_
The referenced packages by the module.
const NetlistPort & portAt(size_t index) const
void addPort(NetlistPort &port)
SignalGroup assignedSignalGroup() const
virtual NetlistPortGroup * clone(bool asMirrored=false) const
void setParent(BaseNetlistBlock *newParent)
NetlistPort * copyTo(BaseNetlistBlock &newParent, std::string newName="") const
void setParent(BaseNetlistBlock *parent)
Signal assignedSignal() const
bool hasParentBlock() const
const BaseNetlistBlock & parentBlock() const
Direction direction() const
std::string name() const
static std::string getUniqueInstanceName(const BaseNetlistBlock &within, const std::string &basename)
size_t parameterCount() const
Definition Netlist.cc:422
bool connect(const NetlistPort &port1, const NetlistPort &port2, int port1FirstBit, int port2FirstBit, int width=1)
Definition Netlist.cc:83
void setParameter(const std::string &name, const std::string &type, const std::string &value)
Definition Netlist.cc:362
Parameter parameter(size_t index) const
Definition Netlist.cc:434
size_t registerPort(NetlistPort &port)
Definition Netlist.cc:309
bool isPortConnected(const NetlistPort &port) const
Definition Netlist.cc:273
void unregisterPort(NetlistPort &port)
Definition Netlist.cc:342
const std::string & packageNameOfConstant() const
Definition Parameter.cc:171
bool valueIsConstant() const
Definition Parameter.cc:166
const TCEString & name() const
Definition Parameter.cc:133
SignalType type() const
Definition Signal.cc:55
virtual void write(const std::string &dstDirectory)
virtual void write(const std::string &dstDirectory)
Definition FUGen.hh:54
@ RESET
Reset signal.
@ CLOCK
Clock signal.
HDL
HDLs supported by ProGe.
Definition ProGeTypes.hh:40
@ Verilog
Verilog.
Definition ProGeTypes.hh:42
@ VHDL
VHDL.
Definition ProGeTypes.hh:41