PandA-2024.02
WB4Intercon_interface.cpp
Go to the documentation of this file.
1 /*
2  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
3  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
4  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
5  * _/ _/ _/ _/ _/ _/ _/ _/ _/
6  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
7  *
8  * ***********************************************
9  * PandA Project
10  * URL: http://panda.dei.polimi.it
11  * Politecnico di Milano - DEIB
12  * System Architectures Group
13  * ***********************************************
14  * Copyright (C) 2004-2024 Politecnico di Milano
15  *
16  * This file is part of the PandA framework.
17  *
18  * The PandA framework is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program. If not, see <http://www.gnu.org/licenses/>.
30  */
31 
39 
40 #include "Parameter.hpp"
41 #include "behavioral_helper.hpp"
42 #include "call_graph_manager.hpp"
43 #include "copyrights_strings.hpp"
44 #include "fileIO.hpp"
45 #include "hls.hpp"
46 #include "hls_device.hpp"
47 #include "hls_manager.hpp"
48 #include "memory.hpp"
49 #include "string_manipulation.hpp"
50 #include "structural_manager.hpp"
51 #include "structural_objects.hpp"
52 #include "technology_manager.hpp"
53 #include "technology_wishbone.hpp"
54 #include "tree_helper.hpp"
55 #include "tree_manager.hpp"
56 
58  unsigned int functionId,
59  const DesignFlowManagerConstRef _design_flow_manager)
60  : WB4_interface(P, HLSManager, functionId, _design_flow_manager,
62 {
63 }
64 
66 
68 static void buildCircuit(structural_managerRef SM, structural_objectRef wrappedObj, structural_objectRef interfaceObj,
69  const hlsRef HLS, const HLS_managerRef HLSMgr);
70 
72 {
74 
75  const structural_managerRef SM = HLS->top;
76 
77  structural_objectRef wrappedObj = SM->get_circ();
78  std::string module_name = wrappedObj->get_id() + "_interconnected";
79 
81  structural_type_descriptorRef module_type =
83  SM_wb4_interconnected->set_top_info(module_name, module_type);
84  structural_objectRef interfaceObj = SM_wb4_interconnected->get_circ();
85 
86  // add the core to the wrapper
87  wrappedObj->set_owner(interfaceObj);
88  wrappedObj->set_id(wrappedObj->get_id() + "_i0");
89 
90  GetPointer<module>(interfaceObj)->add_internal_object(wrappedObj);
92  GetPointer<module>(interfaceObj)
93  ->set_description("WB4 interface for top component: " + wrappedObj->get_typeRef()->id_type);
94  GetPointer<module>(interfaceObj)->set_copyright(GENERATED_COPYRIGHT);
95  GetPointer<module>(interfaceObj)->set_authors("Component automatically generated by bambu");
96  GetPointer<module>(interfaceObj)->set_license(GENERATED_LICENSE);
97 
98  build_bus_interface(SM_wb4_interconnected, HLS, HLSMgr);
99 
100  buildCircuit(SM_wb4_interconnected, wrappedObj, interfaceObj, HLS, HLSMgr);
101 
102  memory::propagate_memory_parameters(interfaceObj, SM_wb4_interconnected);
103 
104  // Generation completed
105  HLS->top = SM_wb4_interconnected;
106 }
107 
108 static unsigned long long get_data_bus_bitsize(const hlsRef HLS, const HLS_managerRef HLSMgr)
109 {
110  const auto function_behavior = HLSMgr->CGetFunctionBehavior(HLS->functionId);
111  const auto behavioral_helper = function_behavior->CGetBehavioralHelper();
112  const auto parameters = HLSMgr->Rmem->get_function_parameters(HLS->functionId);
113 
114  auto data_bus_bitsize = HLSMgr->Rmem->get_bus_data_bitsize();
115  for(const auto& function_parameter : parameters)
116  {
117  if(function_parameter.first != HLS->functionId)
118  {
119  data_bus_bitsize =
120  std::max(data_bus_bitsize,
121  tree_helper::Size(HLSMgr->get_tree_manager()->CGetTreeReindex(function_parameter.first)));
122  }
123  }
124  return data_bus_bitsize;
125 }
126 
127 static unsigned int get_addr_bus_bitsize(const HLS_managerRef HLSMgr)
128 {
129  auto addr_bus_bitsize = HLSMgr->get_address_bitsize();
130  auto allocated_space = HLSMgr->Rmem->get_max_address();
131  unsigned int parameter_addr_bit = 1;
132  while(allocated_space >>= 1)
133  {
134  ++parameter_addr_bit;
135  }
136 
137  return std::max(parameter_addr_bit, addr_bus_bitsize);
138 }
139 
140 static void build_bus_interface(structural_managerRef SM, const hlsRef HLS, const HLS_managerRef HLSMgr)
141 {
142  structural_objectRef interfaceObj = SM->get_circ();
143 
145 
146  auto data_bus_bitsize = get_data_bus_bitsize(HLS, HLSMgr);
147  auto addr_bus_bitsize = get_addr_bus_bitsize(HLSMgr);
148 
150  structural_type_descriptorRef(new structural_type_descriptor("bool", data_bus_bitsize / 8));
152  structural_type_descriptorRef(new structural_type_descriptor("bool", addr_bus_bitsize));
154  structural_type_descriptorRef(new structural_type_descriptor("bool", data_bus_bitsize));
155 
156  // Parameters
157  std::string functionName = tree_helper::name_function(HLSMgr->get_tree_manager(), HLS->functionId);
158  memory::add_memory_parameter(SM, WB_BASE_ADDRESS "_" + functionName + "_interconnected", STR(0));
159 
160  // Common Inputs
161  SM->add_port(CLOCK_PORT_NAME, port_o::IN, interfaceObj, b_type);
162  SM->add_port(RESET_PORT_NAME, port_o::IN, interfaceObj, b_type);
163 
164  // Master Inputs
165  SM->add_port(WB_DATIM_PORT_NAME, port_o::IN, interfaceObj, data_type);
166  SM->add_port(WB_ACKIM_PORT_NAME, port_o::IN, interfaceObj, b_type);
167 
168  // Master Outputs
169  SM->add_port(WB_CYCOM_PORT_NAME, port_o::OUT, interfaceObj, b_type);
170  SM->add_port(WB_STBOM_PORT_NAME, port_o::OUT, interfaceObj, b_type);
171  SM->add_port(WB_WEOM_PORT_NAME, port_o::OUT, interfaceObj, b_type);
172  SM->add_port(WB_ADDROM_PORT_NAME, port_o::OUT, interfaceObj, addr_type);
173  SM->add_port(WB_DATOM_PORT_NAME, port_o::OUT, interfaceObj, data_type);
174  SM->add_port(WB_SELOM_PORT_NAME, port_o::OUT, interfaceObj, sel_type);
175 
176  // Slave Inputs
177  SM->add_port(WB_CYCIS_PORT_NAME, port_o::IN, interfaceObj, b_type);
178  SM->add_port(WB_STBIS_PORT_NAME, port_o::IN, interfaceObj, b_type);
179  SM->add_port(WB_WEIS_PORT_NAME, port_o::IN, interfaceObj, b_type);
180  SM->add_port(WB_ADDRIS_PORT_NAME, port_o::IN, interfaceObj, addr_type);
181  SM->add_port(WB_DATIS_PORT_NAME, port_o::IN, interfaceObj, data_type);
182  SM->add_port(WB_SELIS_PORT_NAME, port_o::IN, interfaceObj, sel_type);
183 
184  // Slave Outputs
185  SM->add_port(WB_DATOS_PORT_NAME, port_o::OUT, interfaceObj, data_type);
186  SM->add_port(WB_ACKOS_PORT_NAME, port_o::OUT, interfaceObj, b_type);
187 }
188 
190  const hlsRef HLS, const HLS_managerRef HLSMgr)
191 {
192  // Clock and reset connection
193  SM->add_connection(interfaceObj->find_member(CLOCK_PORT_NAME, port_o_K, interfaceObj),
194  wrappedObj->find_member(CLOCK_PORT_NAME, port_o_K, wrappedObj));
195 
196  SM->add_connection(interfaceObj->find_member(RESET_PORT_NAME, port_o_K, interfaceObj),
197  wrappedObj->find_member(RESET_PORT_NAME, port_o_K, wrappedObj));
198 
199  const tree_managerRef TM = HLSMgr->get_tree_manager();
200 
202  "intercon", WB4_INTERCON, WBLIBRARY, interfaceObj, HLS->HLS_D->get_technology_manager());
203 
204  auto* interconModule = GetPointer<module>(interconnect);
205  unsigned int interconPortsNumber = interconModule->get_num_ports();
206  for(unsigned int i = 0; i < interconPortsNumber; ++i)
207  {
208  structural_objectRef port = interconModule->get_positional_port(i);
209  std::string portId = port->get_id();
210  if(portId != CLOCK_PORT_NAME && portId != RESET_PORT_NAME)
211  {
212  size_t position = 0;
213  if((position = portId.find("_om")) != std::string::npos)
214  {
215  portId.replace(position, 3, "_is");
216  }
217  else if((position = portId.find("_im")) != std::string::npos)
218  {
219  portId.replace(position, 3, "_os");
220  }
221  else if((position = portId.find("_os")) != std::string::npos)
222  {
223  portId.replace(position, 3, "_im");
224  }
225  else if((position = portId.find("_is")) != std::string::npos)
226  {
227  portId.replace(position, 3, "_om");
228  }
229 
230  structural_objectRef destPort = interfaceObj->find_member(portId, port_o_K, interfaceObj);
231  auto* portPtr = GetPointer<port_o>(port);
232  portPtr->set_type(destPort->get_typeRef());
233  portPtr->add_n_ports(1, port);
234  SM->add_connection(destPort, portPtr->get_port(portPtr->get_ports_size() - 1));
235  }
236  }
237 
238  // Clock and reset connection
239  SM->add_connection(interfaceObj->find_member(CLOCK_PORT_NAME, port_o_K, interfaceObj),
240  interconnect->find_member(CLOCK_PORT_NAME, port_o_K, interconnect));
241 
242  SM->add_connection(interfaceObj->find_member(RESET_PORT_NAME, port_o_K, interfaceObj),
243  interconnect->find_member(RESET_PORT_NAME, port_o_K, interconnect));
244 
245  std::string topFunctionName = tree_helper::name_function(HLSMgr->get_tree_manager(), HLS->functionId);
246  std::string topModuleBaseAddress = WB_BASE_ADDRESS "_" + topFunctionName + "_interconnected";
247 
248  std::vector<structural_objectRef> masters, slaves;
249  slaves.push_back(wrappedObj);
250 
251  std::string baseAddressFileName = "intercon_" + STR(HLS->functionId) + ".mem";
252  std::ofstream baseAddressFile(GetPath(baseAddressFileName));
253 
254  std::string topFunctionBaseAddress = STR(WB_BASE_ADDRESS) + "_" + topFunctionName;
255  wrappedObj->SetParameter(topFunctionBaseAddress, topModuleBaseAddress + " + " + topFunctionBaseAddress);
256 
257  baseAddressFile << std::bitset<8 * sizeof(unsigned int)>(HLSMgr->Rmem->get_first_address(HLS->functionId)) << '\n'
258  << std::bitset<8 * sizeof(unsigned int)>(HLSMgr->Rmem->get_last_address(HLS->functionId, HLSMgr))
259  << '\n';
260 
261  if(wrappedObj->find_member(WB_CYCOM_PORT_NAME, port_o_K, wrappedObj))
262  {
263  masters.push_back(wrappedObj);
264  }
265 
266  const auto additionalTops = HLSMgr->CGetCallGraphManager()->GetAddressedFunctions();
267  for(unsigned int itr : additionalTops)
268  {
269  std::string functionName = tree_helper::name_function(TM, itr);
270  std::string moduleName = functionName + "_minimal_interface_wb4_interface";
271 
272  baseAddressFile << std::bitset<8 * sizeof(unsigned int)>(HLSMgr->Rmem->get_first_address(itr)) << '\n'
273  << std::bitset<8 * sizeof(unsigned int)>(HLSMgr->Rmem->get_last_address(itr, HLSMgr)) << '\n';
275  functionName, moduleName, WORK_LIBRARY, interfaceObj, HLS->HLS_D->get_technology_manager());
276 
277  std::string acceleratorBaseAddress = STR(WB_BASE_ADDRESS) + "_" + functionName;
278  additionalTop->SetParameter(acceleratorBaseAddress, topModuleBaseAddress + " + " + acceleratorBaseAddress);
279 
280  // Clock and reset connection
281  SM->add_connection(interfaceObj->find_member(CLOCK_PORT_NAME, port_o_K, interfaceObj),
282  additionalTop->find_member(CLOCK_PORT_NAME, port_o_K, additionalTop));
283 
284  SM->add_connection(interfaceObj->find_member(RESET_PORT_NAME, port_o_K, interfaceObj),
285  additionalTop->find_member(RESET_PORT_NAME, port_o_K, additionalTop));
286 
287  slaves.push_back(additionalTop);
288  if(additionalTop->find_member(WB_CYCOM_PORT_NAME, port_o_K, additionalTop))
289  {
290  masters.push_back(additionalTop);
291  }
292  }
293 
294  baseAddressFile.close();
295 
297  structural_objectRef irqPort = SM->add_port_vector(WB_IRQ_PORT_NAME, port_o::OUT,
298  static_cast<unsigned int>(slaves.size()), interfaceObj, b_type);
299 
300  unsigned int idx = 0;
301  for(auto itr = slaves.begin(), end = slaves.end(); itr != end; ++itr, ++idx)
302  {
303  // Input ports
304  auto* currentModule = GetPointer<module>(*itr);
305  unsigned int inPortsNumber = currentModule->get_in_port_size();
306  for(unsigned int i = 0; i < inPortsNumber; ++i)
307  {
308  structural_objectRef port = currentModule->get_in_port(i);
309  std::string portId = port->get_id();
310  structural_objectRef destPort = interconnect->find_member(portId, port_o_K, interconnect);
311  if(destPort && portId != CLOCK_PORT_NAME && portId != RESET_PORT_NAME)
312  {
313  structural_objectRef signal =
314  SM->add_sign(currentModule->get_id() + portId, SM->get_circ(), port->get_typeRef());
315  SM->add_connection(port, signal);
316 
317  auto* destPortPtr = GetPointer<port_o>(destPort);
318  destPortPtr->set_type(port->get_typeRef());
319  destPortPtr->add_n_ports(1, destPort);
320  SM->add_connection(signal, destPortPtr->get_port(destPortPtr->get_ports_size() - 1));
321  }
322  }
323 
324  unsigned int outPortsNumber = currentModule->get_out_port_size();
325  for(unsigned int i = 0; i < outPortsNumber; ++i)
326  {
327  structural_objectRef port = currentModule->get_out_port(i);
328  std::string portId = port->get_id();
329  structural_objectRef destPort = interconnect->find_member(portId, port_o_K, interconnect);
330  if(destPort)
331  {
332  structural_objectRef signal =
333  SM->add_sign(currentModule->get_id() + portId, SM->get_circ(), port->get_typeRef());
334  SM->add_connection(port, signal);
335 
336  auto* destPortPtr = GetPointer<port_o>(destPort);
337  destPortPtr->set_type(port->get_typeRef());
338  destPortPtr->add_n_ports(1, destPort);
339  SM->add_connection(signal, destPortPtr->get_port(destPortPtr->get_ports_size() - 1));
340  }
341  }
342 
343  structural_objectRef irqSignal =
344  SM->add_sign(STR(WB_IRQ_PORT_NAME) + "_" + STR(idx) + "_int", SM->get_circ(), b_type);
345 
346  SM->add_connection((*itr)->find_member(WB_IRQ_PORT_NAME, port_o_K, *itr), irqSignal);
347  SM->add_connection(GetPointer<port_o>(irqPort)->get_port(idx), irqSignal);
348  }
349 
350  interconModule->SetParameter("MASTERS", STR(masters.size() + 1));
351  interconModule->SetParameter("SLAVES", STR(slaves.size() + 1));
352  interconModule->SetParameter("MEMORY_INIT_file", "\"\"" + GetPath(baseAddressFileName) + "\"\"");
353 }
static void propagate_memory_parameters(const structural_objectRef src, const structural_managerRef tgt)
Propagates the memory parameters from the source (innermost) module to the target (outermost) one...
Definition: memory.cpp:654
void add_connection(structural_objectRef src, structural_objectRef dest)
Create a connection between a source structural object and a destination structural object...
const HLS_managerRef HLSMgr
information about all the HLS synthesis
Definition: hls_step.hpp:205
Data structure representing the entire HLS information.
WB4Intercon_interface(const ParameterConstRef Param, const HLS_managerRef HLSManager, unsigned int functionId, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
static std::string name_function(const tree_managerConstRef &tm, const unsigned int index)
Return the name of the function.
#define WB_DATIM_PORT_NAME
refcount< structural_type_descriptor > structural_type_descriptorRef
RefCount type definition of the structural_type_descriptor class structure.
Structure representing the most relevant information about the type of a structural object...
const std::string & get_id() const
Return the identifier associated with the structural_object.
static void build_bus_interface(structural_managerRef SM, const hlsRef HLS, const HLS_managerRef HLSMgr)
#define GENERATED_LICENSE
const structural_objectRef get_circ() const
Get a reference to circ field.
#define WBLIBRARY
~WB4Intercon_interface() override
Destructor.
void set_owner(const structural_objectRef new_owner)
set the owner of the structural object
#define WB_DATIS_PORT_NAME
This class manages the circuit structures.
const HLS_deviceRef HLS_D
reference to the information representing the target for the synthesis
Definition: hls.hpp:107
#define WB_BASE_ADDRESS
#define WB_IRQ_PORT_NAME
unsigned int get_addr_bus_bitsize()
Class specification of the manager of the technology library data structures.
Module for the generation of the top WB4 component.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
static void add_memory_parameter(const structural_managerRef SM, const std::string &name, const std::string &value)
Adds the given memory parameter to the corresponding object.
Definition: memory.cpp:725
#define max
Definition: backprop.h:17
#define WB_CYCOM_PORT_NAME
#define CLOCK_PORT_NAME
standard name for ports
structural_managerRef top
Store the top description.
Definition: hls.hpp:164
#define WB_DATOS_PORT_NAME
const size_t P
Definition: helm.c:5
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
unsigned long long get_data_bus_bitsize()
#define WB_STBIS_PORT_NAME
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
HLSFlowStep_Type
Definition: hls_step.hpp:95
static structural_objectRef add_port(const std::string &id, port_o::port_direction pdir, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port.
utility function used to read files.
#define WB_WEIS_PORT_NAME
#define WB_STBOM_PORT_NAME
const ParameterConstRef parameters
Set of input parameters.
static void buildCircuit(structural_managerRef SM, structural_objectRef wrappedObj, structural_objectRef interfaceObj, const hlsRef HLS, const HLS_managerRef HLSMgr)
#define WB_SELIS_PORT_NAME
#define WB4_INTERCON
#define WB_SELOM_PORT_NAME
#define WB_ACKIM_PORT_NAME
refcount< structural_manager > structural_managerRef
RefCount type definition of the structural_manager class structure.
This file collects some utility functions.
#define WB_CYCIS_PORT_NAME
structural_objectRef add_module_from_technology_library(const std::string &id, const std::string &fu_name, const std::string &library_name, const structural_objectRef owner, const technology_managerConstRef TM)
Create a new object starting from a library component.
Utility header to access wishbone technology library.
std::string id_type
Original type id of the structural object.
This class describes all classes used to represent a structural object.
const structural_type_descriptorRef & get_typeRef() const
Return the type descriptor of the structural_object.
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
void set_id(const std::string &s)
Set the identifier associated with the structural_object.
static structural_objectRef add_sign(std::string id, structural_objectRef owner, structural_type_descriptorRef sign_type, unsigned int treenode=0)
Create a new signal.
#define WORK_LIBRARY
working library.
hlsRef HLS
HLS data structure of the function to be analyzed.
#define WB_DATOM_PORT_NAME
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
DesignFlowStep_Status InternalExec() override
Execute the step.
It collects all the common strings covering PandA copyrights issues.
this class is used to manage the command-line or XML options.
unsigned int functionId
this is the identifier of the function to be implemented
Definition: hls.hpp:87
#define WB_ADDRIS_PORT_NAME
#define RESET_PORT_NAME
Wrapper to call graph.
Class implementation of the structural_manager.
#define WB_WEOM_PORT_NAME
#define WB_ACKOS_PORT_NAME
Data structure definition for high-level synthesis flow.
static structural_objectRef add_port_vector(std::string id, port_o::port_direction pdir, unsigned int n_ports, structural_objectRef owner, structural_type_descriptorRef type_descr, unsigned int treenode=0)
Create a new port_vector.
#define GENERATED_COPYRIGHT
Datastructure to represent memory information in high-level synthesis.
Class specification of the manager of the tree structures extracted from the raw file.
HLS specialization of generic_device.
#define WB_ADDROM_PORT_NAME

Generated on Mon Feb 12 2024 13:02:53 for PandA-2024.02 by doxygen 1.8.13