OpenASIP  2.0
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"
35 #include "VirtualNetlistBlock.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"
42 using std::endl;
43 
44 const TCEString XilinxBlockRamGenerator::SP_FILE = "xilinx_blockram.vhdl";
45 const 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 
82  if (connectToArbiter_) {
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 
98 }
99 
100 bool
102  return true;
103 }
104 
105 void
106 XilinxBlockRamGenerator::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  }
116  const ProGe::Direction IN = ProGe::IN;
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 
148 void
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 {
219  connectPorts(
220  integratorBlock, *corePort, *memPort,
221  hdlPort->needsInversion(), coreId);
222  }
223  }
224 }
225 
226 std::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 
242 TCEString
244  TCEString name = "xilinx_";
245  if (connectToArbiter_)
246  name += "dp_";
247  name += "blockram";
248  return name;
249 }
250 
251 
252 TCEString
254  TCEString iname = "onchip_mem_";
255 
256  if (coreId != -1) {
257  iname << "core" << coreId << "_";
258  }
259  return iname << signalPrefix_;
260 }
261 
262 TCEString
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 
273 bool
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 }
MemoryGenerator::platformIntegrator
const PlatformIntegrator * platformIntegrator() const
Definition: MemoryGenerator.cc:225
Netlist.hh
ProGe::NetlistBlock::netlist
virtual const Netlist & netlist() const
Definition: BaseNetlistBlock.cc:348
MemoryGenerator::port
const HDLPort * port(int index) const
Definition: MemoryGenerator.cc:249
PlatformIntegrator::clockPort
ProGe::NetlistPort * clockPort() const
Definition: PlatformIntegrator.cc:692
XilinxBlockRamGenerator::moduleName
virtual TCEString moduleName() const
Definition: XilinxBlockRamGenerator.cc:243
FileSystem.hh
MemoryGenerator::createMemoryNetlistBlock
virtual MemoryGenerator::BlockPair createMemoryNetlistBlock(ProGe::NetlistBlock &integratorBlock, int memIndex, int coreId)
Definition: MemoryGenerator.cc:163
ProGe::NetlistBlock
Definition: NetlistBlock.hh:61
ProGe::Parameter::setValue
void setValue(const TCEString &value)
Definition: Parameter.cc:128
MemoryGenerator::addPort
void addPort(const TCEString &name, HDLPort *port)
Definition: MemoryGenerator.cc:294
HDLPort
Definition: PlatformIntegrator/HDLPort.hh:48
ProGe::BIT_VECTOR
@ BIT_VECTOR
Several bits.
Definition: ProGeTypes.hh:48
XilinxBlockRamGenerator::instanceName
virtual TCEString instanceName(int coreId, int) const
Definition: XilinxBlockRamGenerator.cc:253
XilinxBlockRamGenerator::addMemory
virtual void addMemory(const ProGe::NetlistBlock &ttaCore, ProGe::NetlistBlock &integratorBlock, int memIndex, int coreId)
Definition: XilinxBlockRamGenerator.cc:149
XilinxBlockRamGenerator.hh
XilinxBlockRamGenerator::connectToArbiter_
const bool connectToArbiter_
Definition: XilinxBlockRamGenerator.hh:81
XilinxBlockRamGenerator::almaifPortName
TCEString almaifPortName(const TCEString &portBaseName)
Definition: XilinxBlockRamGenerator.cc:263
XilinxBlockRamGenerator::generatesComponentHdlFile
virtual bool generatesComponentHdlFile() const
Definition: XilinxBlockRamGenerator.cc:101
MemoryGenerator::templatePath
TCEString templatePath() const
Definition: MemoryGenerator.cc:325
XilinxBlockRamGenerator::XilinxBlockRamGenerator
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)
Definition: XilinxBlockRamGenerator.cc:47
Conversion::toString
static std::string toString(const T &source)
ProGe::NetlistBlock::portCount
virtual size_t portCount() const
Definition: BaseNetlistBlock.cc:248
ProGe::Netlist::connect
bool connect(const NetlistPort &port1, const NetlistPort &port2, int port1FirstBit, int port2FirstBit, int width=1)
Definition: Netlist.cc:83
assert
#define assert(condition)
Definition: Application.hh:86
XilinxBlockRamGenerator::almaifBlock_
ProGe::NetlistBlock * almaifBlock_
Definition: XilinxBlockRamGenerator.hh:82
XilinxBlockRamGenerator::addPorts
void addPorts(std::string prefix, int addrWidth, int dataWidth)
Definition: XilinxBlockRamGenerator.cc:106
XilinxBlockRamGenerator::SP_FILE
static const TCEString SP_FILE
Definition: XilinxBlockRamGenerator.hh:90
InvalidData
Definition: Exception.hh:149
PlatformIntegrator::resetPort
ProGe::NetlistPort * resetPort() const
Definition: PlatformIntegrator.cc:704
MemoryGenerator::isCompatible
virtual bool isCompatible(const ProGe::NetlistBlock &ttaCore, int coreId, std::vector< TCEString > &reasons) const
Definition: MemoryGenerator.cc:82
Conversion.hh
ProGe::Parameter
Definition: Parameter.hh:62
NetlistBlock.hh
FileSystem::copy
static void copy(const std::string &source, const std::string &target)
Definition: FileSystem.cc:524
XilinxBlockRamGenerator::isCompatible
virtual bool isCompatible(const ProGe::NetlistBlock &ttaCore, int coreId, std::vector< TCEString > &reasons) const
Definition: XilinxBlockRamGenerator.cc:274
XilinxBlockRamGenerator::generateComponentFile
virtual std::vector< TCEString > generateComponentFile(TCEString outputPath)
Definition: XilinxBlockRamGenerator.cc:227
HDLPort::name
TCEString name() const
Definition: HDLPort.cc:87
HDLPort.hh
ProGe::VirtualNetlistBlock
Definition: VirtualNetlistBlock.hh:52
ProGe::BIT
@ BIT
One bit.
Definition: ProGeTypes.hh:47
XilinxBlockRamGenerator::singleMemoryBlock_
const bool singleMemoryBlock_
Definition: XilinxBlockRamGenerator.hh:85
MemoryGenerator::BlockPair
std::pair< ProGe::NetlistBlock *, ProGe::VirtualNetlistBlock * > BlockPair
Definition: MemoryGenerator.hh:148
FileSystem::DIRECTORY_SEPARATOR
static const std::string DIRECTORY_SEPARATOR
Definition: FileSystem.hh:189
ProGe::OUT
@ OUT
Output port.
Definition: ProGeTypes.hh:54
XilinxBlockRamGenerator::overrideAddrWidth_
const bool overrideAddrWidth_
Definition: XilinxBlockRamGenerator.hh:84
XilinxBlockRamGenerator::DP_FILE
static const TCEString DP_FILE
Definition: XilinxBlockRamGenerator.hh:89
ProGe::NetlistPort::realWidth
int realWidth() const
Definition: NetlistPort.cc:348
MemoryGenerator::corePortName
TCEString corePortName(const TCEString &portBaseName, int coreId) const
Definition: MemoryGenerator.cc:356
MemoryGenerator::connectPorts
virtual void connectPorts(ProGe::NetlistBlock &netlistBlock, const ProGe::NetlistPort &memPort, const ProGe::NetlistPort &corePort, bool inverted, int coreId)
Definition: MemoryGenerator.cc:392
XilinxBlockRamGenerator::~XilinxBlockRamGenerator
virtual ~XilinxBlockRamGenerator()
Definition: XilinxBlockRamGenerator.cc:97
ProGe::NetlistBlock::addSubBlock
void addSubBlock(BaseNetlistBlock *subBlock, const std::string &instanceName="")
Definition: BaseNetlistBlock.cc:405
MemoryGenerator::portCount
int portCount() const
Definition: MemoryGenerator.cc:243
ProGe::DataType
DataType
Data types of hardware ports.
Definition: ProGeTypes.hh:46
TCEString
Definition: TCEString.hh:53
PlatformIntegrator.hh
MemoryGenerator::addParameter
void addParameter(const ProGe::Parameter &add)
Definition: MemoryGenerator.cc:313
HDB::IN
@ IN
Input port.
Definition: HDBTypes.hh:41
VirtualNetlistBlock.hh
ProGe::NetlistPort
Definition: NetlistPort.hh:70
PlatformIntegrator
Definition: PlatformIntegrator.hh:65
MemoryGenerator::portKeyName
TCEString portKeyName(const HDLPort *port) const
Definition: MemoryGenerator.cc:275
MemoryGenerator::memoryTotalWidth
int memoryTotalWidth() const
Definition: MemoryGenerator.cc:193
MemoryGenerator::memoryAddrWidth
int memoryAddrWidth() const
Definition: MemoryGenerator.cc:212
ProGe::Direction
Direction
Direction of the port.
Definition: ProGeTypes.hh:52
ProGe::NetlistBlock::port
virtual NetlistPort * port(const std::string &portName, bool partialMatch=true)
Definition: NetlistBlock.cc:97
Parameter.hh
ProGe::IN
@ IN
Input port.
Definition: ProGeTypes.hh:53
HDB::OUT
@ OUT
Output port.
Definition: HDBTypes.hh:42
FunctionUnit.hh
XilinxBlockRamGenerator::signalPrefix_
TCEString signalPrefix_
Definition: XilinxBlockRamGenerator.hh:83
MemoryGenerator
Definition: MemoryGenerator.hh:85
HDLPort::needsInversion
bool needsInversion() const
Definition: HDLPort.cc:122