OpenASIP 2.2
Loading...
Searching...
No Matches
XilinxBlockRamGenerator.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2016 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 XilinxBlockRamGenerator.cc
26 *
27 * Implementation of XilinxBlockRamGenerator class.
28 */
29
30#include <iostream>
31#include <vector>
33#include "Netlist.hh"
34#include "NetlistBlock.hh"
36#include "HDLPort.hh"
37#include "PlatformIntegrator.hh"
38#include "FileSystem.hh"
39#include "FunctionUnit.hh"
40#include "Conversion.hh"
41 #include "Parameter.hh"
42using std::endl;
43
44const TCEString XilinxBlockRamGenerator::SP_FILE = "xilinx_blockram.vhdl";
45const TCEString XilinxBlockRamGenerator::DP_FILE = "xilinx_dp_blockram.vhdl";
46
48 int memMauWidth, int widthInMaus, int addrWidth, int portBDataWidth,
49 int portBAddrWidth, const PlatformIntegrator* integrator,
50 std::ostream& warningStream, std::ostream& errorStream,
51 bool connectToArbiter, ProGe::NetlistBlock* almaifBlock,
52 TCEString signalPrefix, bool overrideAddrWidth, bool singleMemoryBlock)
54 memMauWidth, widthInMaus, addrWidth, "", integrator, warningStream,
55 errorStream),
56 connectToArbiter_(connectToArbiter),
57 almaifBlock_(almaifBlock),
58 signalPrefix_(signalPrefix),
59 overrideAddrWidth_(overrideAddrWidth),
60 singleMemoryBlock_(singleMemoryBlock) {
61 assert (!connectToArbiter || almaifBlock != nullptr);
62
63 ProGe::Parameter dataw = {"dataw_g", "integer",
65 ProGe::Parameter addrw = {"addrw_g", "integer",
67
68
69 ProGe::Parameter second_dataw = {"dataw_b_g", "integer",
70 Conversion::toString(portBDataWidth)};
71 ProGe::Parameter second_addrw = {"addrw_b_g", "integer",
72 Conversion::toString(portBAddrWidth)};
73
74 if (overrideAddrWidth) {
75 addrw.setValue("local_mem_addrw_g");
76 second_addrw.setValue("local_mem_addrw_g");
77 }
78
79 addParameter(dataw);
80 addParameter(addrw);
81
83 addParameter(second_dataw);
84 addParameter(second_addrw);
85 }
86
87 addPort("clk", new HDLPort("clk", "1", ProGe::BIT, ProGe::IN, false, 1));
88 addPort("rstx", new HDLPort("rstx", "1", ProGe::BIT, ProGe::IN, false, 1));
89 if (connectToArbiter) {
91 addPorts("b_", portBAddrWidth, portBDataWidth);
92 } else {
94 }
95}
96
99
100bool
104
105void
106XilinxBlockRamGenerator::addPorts(std::string pfx, int addrWidth,
107 int dataWidth) {
108 std::string datawGeneric = "dataw_g";
109 std::string addrwGeneric = "addrw_g";
110 if (pfx == "b_") {
111 datawGeneric = "dataw_b_g";
112 addrwGeneric = "addrw_b_g";
113 }
114 const ProGe::DataType BIT = ProGe::BIT;
116 const ProGe::Direction IN = ProGe::IN;
117 const ProGe::Direction OUT = ProGe::OUT;
118 const bool noInvert = false;
119 addPort(pfx + "avalid_out",
120 new HDLPort(pfx + "avalid_in", "1", BIT, IN, noInvert, 1));
121 addPort(pfx + "aready_in",
122 new HDLPort(pfx + "aready_out", "1", BIT, OUT, noInvert, 1));
123 if (!overrideAddrWidth_) {
124 addPort(pfx + "aaddr_out",
125 new HDLPort(pfx + "aaddr_in", addrwGeneric, VEC, IN, noInvert,
126 addrWidth));
127 } else {
128 addPort(pfx + "aaddr_out",
129 new HDLPort(pfx + "aaddr_in", addrwGeneric, VEC, IN, noInvert));
130 }
131 addPort(pfx + "awren_out",
132 new HDLPort(pfx + "awren_in", "1", BIT, IN, noInvert, 1));
133 addPort(pfx + "astrb_out",
134 new HDLPort(pfx + "astrb_in", "(" + datawGeneric + "+7)/8", VEC, IN,
135 noInvert, (dataWidth+7)/8));
136 addPort(pfx + "adata_out",
137 new HDLPort(pfx + "adata_in", datawGeneric, VEC, IN, noInvert,
138 dataWidth));
139 addPort(pfx + "rvalid_in",
140 new HDLPort(pfx + "rvalid_out", "1", BIT, ProGe::OUT, noInvert, 1));
141 addPort(pfx + "rready_out",
142 new HDLPort(pfx + "rready_in", "1", BIT, IN, noInvert, 1));
143 addPort(pfx + "rdata_in",
144 new HDLPort(pfx + "rdata_out", datawGeneric, VEC, OUT, noInvert,
145 dataWidth));
146}
147
148void
150 const ProGe::NetlistBlock& ttaCore,
151 ProGe::NetlistBlock& integratorBlock,
152 int memIndex, int coreId) {
153
154 // Do not instantiate multiple physical memories for shared AS when shared
155 if (coreId > 0 && connectToArbiter_ && singleMemoryBlock_) {
156 return;
157 }
158 BlockPair blocks =
159 createMemoryNetlistBlock(integratorBlock, memIndex, coreId);
160 ProGe::NetlistBlock* mem = blocks.first;
161 ProGe::VirtualNetlistBlock* virt = blocks.second;
162 assert(mem != NULL);
163 assert(virt != NULL);
164
165 if (virt->portCount() > 0) {
166 integratorBlock.addSubBlock(virt);
167 }
168
169 for (int i = 0; i < portCount(); i++) {
170 const HDLPort* hdlPort = port(i);
171 ProGe::NetlistPort* memPort = mem->port(hdlPort->name());
172 if (memPort == NULL) {
173 memPort = virt->port(hdlPort->name());
174 if (memPort == NULL) {
175 TCEString msg = "Port ";
176 msg << hdlPort->name() << " not found from netlist block";
177 throw InvalidData(__FILE__, __LINE__, "MemoryGenerator", msg);
178 }
179 }
180
181
182 TCEString portName = corePortName(portKeyName(hdlPort), coreId);
183 const ProGe::NetlistPort* corePort = NULL;
184 // clock and reset must be connected to new toplevel ports
185 if (portName == platformIntegrator()->clockPort()->name()) {
186 corePort = platformIntegrator()->clockPort();
187 } else if (portName == platformIntegrator()->resetPort()->name()) {
188 corePort = platformIntegrator()->resetPort();
189 } else {
190 if (connectToArbiter_) {
191 portName = almaifPortName(portKeyName(hdlPort));
192 corePort = almaifBlock_->port(portName);
193 } else {
194 corePort = ttaCore.port(portName);
195 }
196 }
197 if (corePort == NULL) {
198 TCEString msg = "Port ";
199 msg << portName << " not found from";
200 if (connectToArbiter_) {
201 msg << " AlmaIF ";
202 } else {
203 msg << " TTA core ";
204 }
205 msg << "netlist block";
206 throw InvalidData(__FILE__, __LINE__, "MemoryGenerator", msg);
207 }
208
210 corePort->realWidth() != memPort->realWidth()) {
211 // Assume a private memory, split wide integrator signals accross
212 // multiple cores
213 int portWidth = memPort->realWidth();
214 // This assumes no ports are inverted
215 integratorBlock.netlist().connect(*memPort, *corePort,
216 0, portWidth*coreId,
217 portWidth);
218 } else {
220 integratorBlock, *corePort, *memPort,
221 hdlPort->needsInversion(), coreId);
222 }
223 }
224}
225
226std::vector<TCEString>
228 TCEString inputFile =
231 TCEString outputFile;
232 outputFile << outputPath << FileSystem::DIRECTORY_SEPARATOR
233 << moduleName() << ".vhdl";
234
235 FileSystem::copy(inputFile, outputPath);
236 std::vector<TCEString> files;
237 files.push_back(outputFile);
238 return files;
239}
240
241
244 TCEString name = "xilinx_";
246 name += "dp_";
247 name += "blockram";
248 return name;
249}
250
251
254 TCEString iname = "onchip_mem_";
255
256 if (coreId != -1) {
257 iname << "core" << coreId << "_";
258 }
259 return iname << signalPrefix_;
260}
261
264 // clock and reset port names are global
265 if (portBaseName == platformIntegrator()->clockPort()->name() ||
266 portBaseName == platformIntegrator()->resetPort()->name()) {
267 return portBaseName;
268 }
269
270 return signalPrefix_ + "_" + portBaseName;
271}
272
273bool
275 int coreId, std::vector<TCEString>& reasons) const {
276 if (connectToArbiter_) {
277 // TODO: Actually check almaifBlock_ ports?
278 return true;
279 } else {
280 return MemoryGenerator::isCompatible(ttaCore, coreId, reasons);
281 }
282}
#define assert(condition)
static std::string toString(const T &source)
static const std::string DIRECTORY_SEPARATOR
static void copy(const std::string &source, const std::string &target)
TCEString name() const
Definition HDLPort.cc:87
bool needsInversion() const
Definition HDLPort.cc:122
TCEString portKeyName(const HDLPort *port) const
const PlatformIntegrator * platformIntegrator() const
const HDLPort * port(int index) const
void addParameter(const ProGe::Parameter &add)
std::pair< ProGe::NetlistBlock *, ProGe::VirtualNetlistBlock * > BlockPair
void addPort(const TCEString &name, HDLPort *port)
int memoryTotalWidth() const
virtual bool isCompatible(const ProGe::NetlistBlock &ttaCore, int coreId, std::vector< TCEString > &reasons) const
int memoryAddrWidth() const
virtual void connectPorts(ProGe::NetlistBlock &netlistBlock, const ProGe::NetlistPort &memPort, const ProGe::NetlistPort &corePort, bool inverted, int coreId)
TCEString corePortName(const TCEString &portBaseName, int coreId) const
TCEString templatePath() const
int portCount() const
virtual MemoryGenerator::BlockPair createMemoryNetlistBlock(ProGe::NetlistBlock &integratorBlock, int memIndex, int coreId)
ProGe::NetlistPort * resetPort() const
ProGe::NetlistPort * clockPort() const
void addSubBlock(BaseNetlistBlock *subBlock, const std::string &instanceName="")
virtual NetlistPort * port(const std::string &portName, bool partialMatch=true)
virtual size_t portCount() const
virtual const Netlist & netlist() const
int realWidth() const
bool connect(const NetlistPort &port1, const NetlistPort &port2, int port1FirstBit, int port2FirstBit, int width=1)
Definition Netlist.cc:83
void setValue(const TCEString &value)
Definition Parameter.cc:128
virtual TCEString moduleName() const
virtual void addMemory(const ProGe::NetlistBlock &ttaCore, ProGe::NetlistBlock &integratorBlock, int memIndex, int coreId)
static const TCEString DP_FILE
static const TCEString SP_FILE
virtual std::vector< TCEString > generateComponentFile(TCEString outputPath)
virtual bool isCompatible(const ProGe::NetlistBlock &ttaCore, int coreId, std::vector< TCEString > &reasons) const
TCEString almaifPortName(const TCEString &portBaseName)
ProGe::NetlistBlock * almaifBlock_
virtual bool generatesComponentHdlFile() const
XilinxBlockRamGenerator(int memMauWidth, int widthInMaus, int addrWidth, int portBDataWidth, int portBAddrWidth, const PlatformIntegrator *integrator, std::ostream &warningStream, std::ostream &errorStream, bool connectToArbiter=false, ProGe::NetlistBlock *almaifBlocks=nullptr, TCEString signalPrefix="", bool overrideAddrWidth=false, bool singleMemoryBlock=false)
void addPorts(std::string prefix, int addrWidth, int dataWidth)
virtual TCEString instanceName(int coreId, int) const
DataType
Data types of hardware ports.
Definition ProGeTypes.hh:46
@ BIT
One bit.
Definition ProGeTypes.hh:47
@ BIT_VECTOR
Several bits.
Definition ProGeTypes.hh:48
Direction
Direction of the port.
Definition ProGeTypes.hh:52
@ OUT
Output port.
Definition ProGeTypes.hh:54
@ IN
Input port.
Definition ProGeTypes.hh:53