PandA-2024.02
BuiltinWaitCallModuleGenerator.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2022-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
47 
48 #include "application_manager.hpp"
49 #include "function_behavior.hpp"
50 #include "hls_manager.hpp"
51 #include "language_writer.hpp"
52 #include "math_function.hpp"
53 #include "op_graph.hpp"
54 #include "structural_objects.hpp"
55 #include "tree_helper.hpp"
56 #include "tree_manager.hpp"
57 #include "tree_reindex.hpp"
58 
60 {
61 }
62 
64  unsigned int function_id, vertex op_v,
65  const HDLWriter_Language /* language */,
66  const std::vector<ModuleGenerator::parameter>& _p,
67  const std::vector<ModuleGenerator::parameter>& /* _ports_in */,
68  const std::vector<ModuleGenerator::parameter>& /* _ports_out */,
69  const std::vector<ModuleGenerator::parameter>& /* _ports_inout */)
70 {
71  const auto retval_size = [&]() {
72  THROW_ASSERT(function_id && op_v, "");
73  const auto FB = HLSMgr->CGetFunctionBehavior(function_id);
74  const auto TM = HLSMgr->get_tree_manager();
75  const auto call_stmt =
76  TM->CGetTreeNode(FB->CGetOpGraph(FunctionBehavior::CFG)->CGetOpNodeInfo(op_v)->GetNodeId());
77  THROW_ASSERT(call_stmt && call_stmt->get_kind() == gimple_call_K, "Expected gimple call statement.");
78  const auto gc = GetPointerS<const gimple_call>(call_stmt);
79  THROW_ASSERT(gc->args.size() >= 2, "Expected at least two arguments for the builtin wait call.");
80  const auto called_addr = gc->args.at(0);
81  const auto called_hasreturn = gc->args.at(1);
82  THROW_ASSERT(GET_CONST_NODE(called_hasreturn)->get_kind() == integer_cst_K, "");
83  if(tree_helper::GetConstValue(called_hasreturn))
84  {
85  const auto fpointer_type = tree_helper::CGetType(called_addr);
86  const auto called_ftype = tree_helper::CGetPointedType(fpointer_type);
87  const auto return_type = tree_helper::GetFunctionReturnType(called_ftype);
88  if(return_type)
89  {
90  return tree_helper::Size(return_type);
91  }
92  }
93  return 0ULL;
94  }();
95 
96  // Signals declarations
97  if(_p.size() == 3U)
98  {
99  out << "reg [0:0] index;\n\n";
100  }
101  else if(_p.size() > 3U)
102  {
103  out << "reg [" << ceil_log2(_p.size() - 2U) << "-1:0] index;\n\n";
104  }
105  if(_p.size() > 2U)
106  {
107  out << "wire [BITSIZE_Mout_addr_ram-1:0] paramAddressRead;\n\n";
108  }
109  out << "reg [31:0] step;\n"
110  << "reg [31:0] next_step;\n"
111  << "reg done_port;\n"
112  << "reg Sout_DataRdy;\n"
113  << "reg Mout_oe_ram;\n"
114  << "reg Mout_we_ram;\n"
115  << "reg [BITSIZE_Mout_addr_ram-1:0] Mout_addr_ram;\n"
116  << "reg [BITSIZE_Mout_Wdata_ram-1:0] Mout_Wdata_ram;\n"
117  << "reg [BITSIZE_Mout_data_ram_size-1:0] Mout_data_ram_size;\n"
118  << "reg active_request;\n"
119  << "reg active_request_next;\n\n";
120  if(retval_size)
121  {
122  out << "reg [" << retval_size << "-1:0] readValue 1INIT_ZERO_VALUE;\n"
123  << "reg [" << retval_size << "-1:0] next_readValue;\n\n";
124  }
125 
126  if(_p.size() > 2U)
127  {
128  out << "reg [BITSIZE_Mout_addr_ram-1:0] paramAddress [" << (_p.size() - 2U) << "-1:0];\n\n";
129  }
130 
131  const auto n_iterations = retval_size ? (_p.size() + 3U) : _p.size();
132 
133  out << "parameter [31:0] ";
134  for(auto idx = 0U; idx <= n_iterations; ++idx)
135  {
136  if(idx != n_iterations)
137  {
138  out << "S_" << idx << " = 32'd" << idx << ",\n";
139  }
140  else
141  {
142  out << "S_" << idx << " = 32'd" << idx << ";\n";
143  }
144  }
145 
146  if(_p.size() > 2U)
147  {
148  out << "initial\n"
149  << " begin\n"
150  << " $readmemb(MEMORY_INIT_file, paramAddress, 0, " << (_p.size() - 2U) << "-1);\n"
151  << " end\n\n\n";
152  }
153 
154  if(_p.size() > 2U)
155  {
156  out << "assign paramAddressRead = paramAddress[index];\n";
157  }
158  out << "assign Sout_Rdata_ram = Sin_Rdata_ram;\n";
159 
160  out << "always @ (posedge clock 1RESET_EDGE)\n"
161  << " if (1RESET_VALUE)\n"
162  << " begin\n"
163  << " active_request <= 0;\n"
164  << " end\n"
165  << " else\n"
166  << " begin\n"
167  << " active_request <= active_request_next;\n"
168  << " end\n";
169 
170  // State machine
171  out << "always @ (posedge clock 1RESET_EDGE)\n"
172  << " if (1RESET_VALUE)\n"
173  << " begin\n"
174  << " step <= 0;\n";
175 
176  if(retval_size)
177  {
178  if(retval_size == 1U)
179  {
180  out << " readValue <= {1'b0};\n";
181  }
182  else
183  {
184  out << " readValue <= {" << retval_size << " {1'b0}};\n";
185  }
186  out << " end else begin\n"
187  << " step <= next_step;\n"
188  << " readValue <= next_readValue;\n"
189  << " end\n\n";
190  }
191  else
192  {
193  out << " end else begin\n"
194  << " step <= next_step;\n"
195  << " end\n\n";
196  }
197 
198  if(_p.size() > 2U)
199  {
200  out << "always @(*)\n"
201  << " begin\n"
202  << " index = 0;\n"
203  << " if (step == S_0) begin\n"
204  << " index = 0;\n"
205  << " end\n";
206  }
207 
208  auto idx = 1U;
209  if(_p.size() > 3U)
210  {
211  for(idx = 1U; idx <= _p.size() - 3U; ++idx)
212  {
213  out << " else if (step == S_" << idx << ") begin\n"
214  << " index = " << idx - 1U << ";\n"
215  << " end\n";
216  }
217  }
218 
219  if(_p.size() > 2U)
220  {
221  out << " else if (step == S_" << idx << ") begin\n"
222  << " index = " << idx - 1U << ";\n"
223  << " end\n";
224  idx++;
225  }
226 
227  idx++;
228 
229  idx++;
230 
231  if(_p.size() > 2U && retval_size)
232  {
233  out << " else if (step == S_" << idx << ") begin\n"
234  << " index = " << idx - 4U << ";\n"
235  << " end\n";
236  idx++;
237  }
238  if(_p.size() > 2U)
239  {
240  out << "end\n";
241  }
242 
243  out << "always @(*)\n"
244  << " begin\n"
245  << " Sout_DataRdy = Sin_DataRdy;\n"
246  << " done_port = 1'b0;\n"
247  << " next_step = S_0;\n"
248  << (retval_size ? " next_readValue = readValue;\n" : "") << " Mout_we_ram = Min_we_ram;\n"
249  << " Mout_Wdata_ram = Min_Wdata_ram;\n"
250  << " Mout_oe_ram = Min_oe_ram;\n"
251  << " Mout_addr_ram = Min_addr_ram;\n"
252  << " Mout_data_ram_size = Min_data_ram_size;\n"
253  << " active_request_next = 0;\n"
254  << " if (step == S_0) begin\n"
255  << " if (start_port == 1'b1) begin\n"
256  << " active_request_next = 1;\n";
257  if(_p.size() == 3U)
258  {
259  out << " next_step = in2[0] ? S_2 : S_1;\n";
260  }
261  else
262  {
263  out << " next_step = S_1;\n";
264  }
265  out << " end else begin\n"
266  << " next_step = S_0;\n"
267  << " end\n"
268  << " end\n";
269  idx = 1U;
270 
271  if(_p.size() > 3U)
272  {
273  for(idx = 1U; idx <= _p.size() - 3U; ++idx)
274  {
275  if(idx != _p.size() - 3U)
276  {
277  out << " else if (step == S_" << idx << ") begin\n"
278  << " Mout_we_ram = active_request;\n"
279  << " Mout_addr_ram = (in1 + paramAddressRead) & {BITSIZE_Mout_addr_ram{active_request}};\n"
280  << " Mout_Wdata_ram = " << _p[idx + 1].name << " & {BITSIZE_Mout_Wdata_ram{active_request}};\n"
281  << " Mout_data_ram_size = " << _p[idx + 1].type_size
282  << " & {BITSIZE_Mout_data_ram_size{active_request}};\n"
283  << " if (M_DataRdy == 1'b1) begin\n"
284  << " next_step = S_" << idx + 1U << ";\n"
285  << " active_request_next = 1;\n"
286  << " end else begin\n"
287  << " next_step = S_" << idx << ";\n"
288  << " end\n"
289  << " end\n";
290  }
291  else
292  {
293  out << " else if (step == S_" << idx << ") begin\n"
294  << " Mout_we_ram = active_request;\n"
295  << " Mout_addr_ram = (in1 + paramAddressRead) & {BITSIZE_Mout_addr_ram{active_request}};\n"
296  << " Mout_Wdata_ram = " << _p[idx + 1].name << " & {BITSIZE_Mout_Wdata_ram{active_request}};\n"
297  << " Mout_data_ram_size = " << _p[idx + 1].type_size
298  << " & {BITSIZE_Mout_data_ram_size{active_request}};\n"
299  << " if (M_DataRdy == 1'b1) begin\n"
300  << " next_step = in2[0] ? S_" << idx + 2U << " : S_" << idx + 1U << ";\n"
301  << " active_request_next = 1;\n"
302  << " end else begin\n"
303  << " next_step = S_" << idx << ";\n"
304  << " end\n"
305  << " end\n";
306  }
307  }
308  }
309  if(_p.size() > 2U)
310  {
311  out << " else if (step == S_" << idx << ") begin\n"
312  << " Mout_we_ram = active_request;\n"
313  << " Mout_addr_ram = (in1 + paramAddressRead) & {BITSIZE_Mout_addr_ram{active_request}};\n"
314  << " Mout_Wdata_ram = " << _p[idx + 1].name << " & {BITSIZE_Mout_Wdata_ram{active_request}};\n"
315  << " Mout_data_ram_size = " << _p[idx + 1].type_size
316  << " & {BITSIZE_Mout_data_ram_size{active_request}};\n"
317  << " if (M_DataRdy == 1'b1) begin\n"
318  << " next_step = S_" << idx + 1U << ";\n"
319  << " active_request_next = 1;\n"
320  << " end else begin\n"
321  << " next_step = S_" << idx << ";\n"
322  << " end\n"
323  << " end\n";
324  idx++;
325  }
326 
327  out << " else if (step == S_" << idx << ") begin\n"
328  << " Mout_we_ram = active_request;\n"
329  << " Mout_addr_ram = in1 & {BITSIZE_Mout_addr_ram{active_request}};\n"
330  << " Mout_Wdata_ram = unlock_address & {BITSIZE_Mout_Wdata_ram{active_request}};\n"
331  << " Mout_data_ram_size = BITSIZE_Mout_Wdata_ram & {BITSIZE_Mout_data_ram_size{active_request}};\n"
332  << " if (M_DataRdy == 1'b1) begin\n"
333  << " next_step = S_" << idx + 1U << ";\n"
334  << " active_request_next = 1;\n"
335  << " end else begin\n"
336  << " next_step = S_" << idx << ";\n"
337  << " end"
338  << " end\n";
339  idx++;
340 
341  out << " else if (step == S_" << idx << ") begin\n"
342  << " if (S_we_ram == 1 && S_addr_ram == unlock_address) begin\n"
343  << " Sout_DataRdy = 1'b1;\n"
344  << " next_step = in2[0] ? S_" << (retval_size ? idx + 1U : 0U) << " : S_0;\n"
345  << " active_request_next = 1;\n"
346  << " done_port = in2[0] ? 1'b0 : 1'b1;\n"
347  << " end else begin\n"
348  << " next_step = S_" << idx << ";\n"
349  << " end\n"
350  << " end\n";
351  idx++;
352 
353  if(_p.size() > 2U && retval_size)
354  {
355  out << " else if (step == S_" << idx << ") begin\n"
356  << " Mout_oe_ram = active_request;\n"
357  << " Mout_addr_ram = (in1 + paramAddressRead) & {BITSIZE_Mout_addr_ram{active_request}};\n"
358  << " Mout_data_ram_size = " << retval_size << " & {BITSIZE_Mout_data_ram_size{active_request}};\n"
359  << " if (M_DataRdy == 1'b1) begin\n"
360  << " next_step = S_" << idx + 1U << ";\n"
361  << " active_request_next = 1;\n"
362  << " next_readValue = M_Rdata_ram;\n"
363  << " end else begin\n"
364  << " next_step = S_" << idx << ";\n"
365  << " end"
366  << " end\n";
367  idx++;
368 
369  out << " else if (step == S_" << idx << ") begin\n"
370  << " Mout_we_ram = active_request;\n"
371  << " Mout_addr_ram = " << _p[_p.size() - 1U].name << " & {BITSIZE_Mout_addr_ram{active_request}};\n"
372  << " Mout_Wdata_ram = readValue & {BITSIZE_Mout_Wdata_ram{active_request}};\n"
373  << " Mout_data_ram_size = " << retval_size << " & {BITSIZE_Mout_data_ram_size{active_request}};\n"
374  << " if (M_DataRdy == 1'b1) begin\n"
375  << " next_step = S_0;\n"
376  << " active_request_next = 1;\n"
377  << " done_port = 1'b1;\n"
378  << " end else begin\n"
379  << " next_step = S_" << idx << ";\n"
380  << " end"
381  << " end\n";
382  }
383  out << "end\n";
384 }
Data structure representing the entire HLS information.
Definition of the class representing a generic C application.
mathematical utility function not provided by standard libraries
HDLWriter_Language
T ceil_log2(T x)
Return the smallest n such that 2**n >= X.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
Control flow graph.
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
void InternalExec(std::ostream &out, structural_objectRef mod, unsigned int function_id, vertex op_v, const HDLWriter_Language language, const std::vector< ModuleGenerator::parameter > &_p, const std::vector< ModuleGenerator::parameter > &_ports_in, const std::vector< ModuleGenerator::parameter > &_ports_out, const std::vector< ModuleGenerator::parameter > &_ports_inout) final
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
This file collects some utility functions.
This class describes all classes used to represent a structural object.
Class specification of the tree_reindex support class.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static tree_nodeConstRef CGetPointedType(const tree_nodeConstRef &pointer)
Return the pointed type of a pointer object.
BuiltinWaitCallModuleGenerator(const HLS_managerRef &HLSMgr)
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

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