PandA-2024.02
control_flow_checker.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) 2017-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  */
36 #include "control_flow_checker.hpp"
37 
38 #include "Discrepancy.hpp"
39 #include "Parameter.hpp"
40 #include "behavioral_helper.hpp"
41 #include "copyrights_strings.hpp"
42 #include "custom_map.hpp"
43 #include "custom_set.hpp"
44 #include "function_behavior.hpp"
45 #include "hls.hpp"
46 #include "hls_device.hpp"
47 #include "hls_manager.hpp"
48 #include "language_writer.hpp"
51 #include "string_manipulation.hpp"
52 #include "structural_manager.hpp"
53 #include "utility.hpp"
54 
55 #include <boost/algorithm/string/case_conv.hpp>
56 #include <utility/fileIO.hpp>
57 
58 #include <algorithm>
59 #include <string>
60 #include <tuple>
61 
63  unsigned int _funId, const DesignFlowManagerConstRef _design_flow_manager)
64  : HLSFunctionStep(_Param, _HLSMgr, _funId, _design_flow_manager, HLSFlowStep_Type::CONTROL_FLOW_CHECKER)
65 {
66  debug_level = parameters->get_class_debug_level(GET_CLASS(*this));
67 }
68 
70 
73 {
75  switch(relationship_type)
76  {
78  {
79  ret.insert(std::make_tuple(parameters->getOption<HLSFlowStep_Type>(OPT_stg_algorithm),
81  break;
82  }
85  {
86  break;
87  }
88  default:
89  {
91  break;
92  }
93  }
94  return ret;
95 }
96 
97 bool ControlFlowChecker::IsOneHotFSM(unsigned int function_id, const HLS_managerRef HLSMgr)
98 {
99  const auto vendor = [&]() -> std::string {
100  const auto tgt_device = HLSMgr->get_HLS_device();
101  if(tgt_device->has_parameter("vendor"))
102  {
103  return tgt_device->get_parameter<std::string>("vendor");
104  }
105  return "";
106  }();
107  if(HLSMgr->get_parameter()->getOption<std::string>(OPT_fsm_encoding) == "one-hot" ||
108  (HLSMgr->get_parameter()->getOption<std::string>(OPT_fsm_encoding) == "auto" &&
109  boost::iequals(vendor, "xilinx") && HLSMgr->get_HLS(function_id)->STG->get_number_of_states() < 256))
110  {
111  return true;
112  }
113 
114  return false;
115 }
116 
117 static unsigned int comp_state_bitsize(bool one_hot_encoding, const HLS_managerRef HLSMgr, const unsigned int f_id,
118  unsigned max_value)
119 {
120  unsigned int n_states = HLSMgr->get_HLS(f_id)->STG->get_number_of_states();
121  unsigned int bitsnumber = language_writer::bitnumber(n_states - 1);
122  if(max_value != n_states - 1)
123  {
124  bitsnumber = language_writer::bitnumber(max_value);
125  }
126 
127  unsigned int state_bitsize = one_hot_encoding ? (max_value + 1) : bitsnumber;
128 
129  return state_bitsize;
130 }
131 
132 static std::string create_control_flow_checker(size_t epp_trace_bitsize, const unsigned int f_id,
134  const HWDiscrepancyInfoConstRef& discr_info, bool one_hot_encoding,
135  unsigned max_value, unsigned int state_bitsize,
137 {
139  const auto& eppstg = STG->CGetEPPStg();
140  const auto& stg = STG->CGetStg();
141  const auto& stg_info = stg->CGetStateTransitionGraphInfo();
142 
143  std::string result =
144  "parameter METADATA_BITS_HELPER_SIZE = (EPP_TRACE_METADATA_BITSIZE > 0) ? EPP_TRACE_METADATA_BITSIZE : 1;\n"
145  "generate\n"
146  "if(EPP_TRACE_LENGTH>0)\n"
147  "begin\n"
148  "// internal signals\n"
149  "// signals concering the state of the checker\n"
150  "reg checker_state;\n"
151  "reg next_checker_state;\n"
152  "wire is_checking;\n\n"
153  "// epp counters, increments, and resets\n"
154  "reg [EPP_TRACE_BITSIZE - 1 : 0] prev_epp_counter;\n"
155  "reg [EPP_TRACE_BITSIZE - 1 : 0] epp_counter;\n"
156  "wire [EPP_TRACE_BITSIZE - 1 : 0] next_epp_counter;\n"
157  "wire [EPP_TRACE_BITSIZE - 1 : 0] epp_incremented_counter;\n"
158  "reg [EPP_TRACE_BITSIZE - 1 : 0] epp_increment_val;\n"
159  "reg [EPP_TRACE_BITSIZE - 1 : 0] epp_reset_val;\n\n"
160  "reg epp_to_reset;\n"
161  "// info about if we're checking now or the previous feedback edge\n"
162  "reg to_check_now;\n"
163  "reg to_check_prev;\n"
164  "reg next_to_check_prev;\n\n"
165  "// trace offsets and increments\n"
166  "reg [BITSIZE_out_mismatch_trace_offset - 1 : 0] prev_epp_trace_offset;\n"
167  "reg [BITSIZE_out_mismatch_trace_offset - 1 : 0] epp_trace_offset;\n"
168  "wire [BITSIZE_out_mismatch_trace_offset - 1 : 0] next_epp_trace_offset;\n"
169  "wire trace_offset_increment;\n"
170  "wire trace_offset_increment_compressed;\n"
171  "reg trace_offset_increment_compressed_reg;\n\n"
172  "// wires and register for data read from the trace\n"
173  "wire [METADATA_BITS_HELPER_SIZE - 1 : 0] trace_metadata;\n"
174  "wire [METADATA_BITS_HELPER_SIZE - 1 : 0] metadata;\n"
175  "wire [METADATA_BITS_HELPER_SIZE - 1 : 0] decremented_metadata;\n"
176  "reg [METADATA_BITS_HELPER_SIZE - 1 : 0] decremented_metadata_reg;\n"
177  "wire [EPP_TRACE_BITSIZE - 1 : 0] trace_data;\n"
178  "reg [EPP_TRACE_BITSIZE - 1 : 0] prev_data;\n\n"
179  "// trace memory\n"
180  "reg [EPP_TRACE_METADATA_BITSIZE + EPP_TRACE_BITSIZE - 1 : 0] epp_trace_memory [0 : EPP_TRACE_LENGTH-1] /* "
181  "synthesis syn_ramstyle = \"no_rw_check, M20K\" */;\n"
182  "reg [EPP_TRACE_METADATA_BITSIZE + EPP_TRACE_BITSIZE - 1 : 0] epp_trace_reg;\n\n"
183  "// mismatch conditions\n"
184  "wire [BITSIZE_out_mismatch_trace_offset - 1 : 0] mismatch_trace_offset;\n"
185  "wire mismatch_now;\n"
186  "wire mismatch_prev;\n\n"
187  "// registered inputs\n"
188  "reg " START_PORT_NAME "_reg;\n"
189  "reg " DONE_PORT_NAME "_reg;\n"
190  "reg [STATE_BITSIZE-1:0] " PRESENT_STATE_PORT_NAME "_reg;\n"
191  "reg [STATE_BITSIZE-1:0] " NEXT_STATE_PORT_NAME "_reg;\n\n";
192 
193  result += "always @(posedge " CLOCK_PORT_NAME ")\n"
194  "begin\n"
195  " " START_PORT_NAME "_reg <= " START_PORT_NAME ";\n"
196  "end\n\n";
197 
198  result += "always @(posedge " CLOCK_PORT_NAME ")\n"
199  "begin\n"
200  " " DONE_PORT_NAME "_reg <= " DONE_PORT_NAME ";\n"
201  "end\n\n";
202 
203  result += "always @(posedge " CLOCK_PORT_NAME ")\n"
204  "begin\n"
206  "end\n\n";
207 
208  result += "always @(posedge " CLOCK_PORT_NAME ")\n"
209  "begin\n"
210  " " NEXT_STATE_PORT_NAME "_reg <= " NEXT_STATE_PORT_NAME ";\n"
211  "end\n\n";
212 
213  result += "initial\n"
214  "begin\n"
215  " $readmemb(MEMORY_INIT_file, epp_trace_memory, 0, EPP_TRACE_LENGTH-1);\n"
216  "end\n\n";
217 
218  result += "assign epp_incremented_counter = epp_counter + epp_increment_val;\n"
219  "assign next_epp_counter = epp_to_reset ? epp_reset_val : epp_incremented_counter;\n\n";
220 
221  result +=
222  "assign trace_offset_increment = is_checking && ((to_check_now && !to_check_prev) || next_to_check_prev);\n"
223  "if (EPP_TRACE_METADATA_BITSIZE > 0)\n"
224  "begin\n"
225  " assign {trace_metadata, trace_data} = epp_trace_reg;\n"
226  " assign metadata = (trace_offset_increment_compressed_reg) ? trace_metadata : decremented_metadata_reg;\n"
227  " assign decremented_metadata = metadata - trace_offset_increment;\n"
228  " assign trace_offset_increment_compressed = (metadata == 0) && trace_offset_increment;\n"
229  "end\n"
230  "else\n"
231  "begin\n"
232  " assign trace_data = epp_trace_reg;\n"
233  " assign trace_offset_increment_compressed = trace_offset_increment;\n"
234  "end\n"
235  "assign next_epp_trace_offset = epp_trace_offset + trace_offset_increment_compressed;\n\n";
236 
237  result += "assign is_checking = checker_state || " START_PORT_NAME "_reg;\n"
238  "assign mismatch_now = (!to_check_prev) && to_check_now && (epp_counter != trace_data);\n"
239  "assign mismatch_prev = to_check_prev && (prev_epp_counter != prev_data);\n"
240  "assign out_mismatch = is_checking && (mismatch_now || mismatch_prev);\n"
241  "assign out_mismatch_id = out_mismatch ? EPP_MISMATCH_ID : 0;\n"
242  "assign mismatch_trace_offset = mismatch_prev ? prev_epp_trace_offset : epp_trace_offset;\n"
243  "assign out_mismatch_trace_offset = out_mismatch ? mismatch_trace_offset : 0;\n\n";
244 
245  result += "// synthesis translate_off\n"
246  "always @(posedge " CLOCK_PORT_NAME ")\n"
247  "begin\n"
248  " if (out_mismatch)\n"
249  " begin\n"
250  " $display(\"DISCREPANCY FOUND at time %t:\", $time);\n"
251  " $display(\"DISCREPANCY ID: %d\", out_mismatch_id);\n"
252  " $display(\"trace_offset: %d\", out_mismatch_trace_offset);\n"
253  " $finish;\n"
254  " end\n"
255  "end\n"
256  "// synthesis translate_on\n";
257 
258  result += "// update state of the checker\n"
259  "always @(*)\n"
260  "begin\n"
261  " next_checker_state = checker_state;\n"
262  " case (checker_state)\n"
263  " 0:\n"
264  " begin\n"
265  " if (" START_PORT_NAME "_reg && ! " DONE_PORT_NAME "_reg)\n"
266  " next_checker_state = 1;\n"
267  " end\n"
268  " 1:\n"
269  " begin\n"
270  " if (" DONE_PORT_NAME "_reg)\n"
271  " next_checker_state = 0;\n"
272  " end\n"
273  " default:\n"
274  " next_checker_state = 0;\n"
275  " endcase\n"
276  "end\n\n";
277 
278  // helper functions
279  const auto encode_one_hot = [](unsigned int nstates, unsigned int val) -> std::string {
280  std::string res;
281  for(unsigned int i = 0; i < nstates; ++i)
282  {
283  res = (val == i ? "1" : "0") + res;
284  }
285  return res;
286  };
287  const auto compute_state_string = [one_hot_encoding, max_value, state_bitsize,
288  encode_one_hot](unsigned int state_id) -> std::string {
289  return one_hot_encoding ? (STR(state_bitsize) + "'b" + encode_one_hot(max_value + 1, state_id)) :
290  (STR(state_bitsize) + "'d" + STR(state_id));
291  };
292 
293  // compute if this state is to check
294  {
295  result += "// compute if this state is to check\n"
296  "always @(*)\n"
297  "begin\n"
298  " case (" PRESENT_STATE_PORT_NAME "_reg)";
299 
300  bool is_first = true;
301  for(const auto s_id : discr_info->fu_id_to_states_to_check.at(f_id))
302  {
303  const std::string state_string = compute_state_string(s_id);
304  if(not is_first)
305  {
306  result += ',';
307  }
308  result += "\n " + state_string;
309  is_first = false;
310  }
311 
312  result += ":\n"
313  " to_check_now = 1;\n";
314 
315  result += " default:\n"
316  " to_check_now = 0;\n"
317  " endcase\n"
318  "end\n\n";
319  }
320 
321  const auto fsm_entry_node = stg_info->entry_node;
322  const auto fsm_exit_node = stg_info->exit_node;
323  // compute if at the next cycle we have to check the previous state
324  {
325  result += "// compute if at the next cycle we have to check the previous state\n"
326  "always @(*)\n"
327  "begin\n"
328  " case (" PRESENT_STATE_PORT_NAME "_reg)\n";
329 
330  BOOST_FOREACH(vertex state, boost::vertices(*stg))
331  {
332  if(state == fsm_entry_node or state == fsm_exit_node)
333  {
334  continue;
335  }
336  bool a = true;
337  BOOST_FOREACH(EdgeDescriptor out_edge, boost::out_edges(state, *stg))
338  {
339  if(stg->GetSelector(out_edge) & TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK)
340  {
341  const vertex dst = boost::target(out_edge, *stg);
342  const auto dst_id = stg_info->vertex_to_state_id.at(dst);
343  if(discr_info->fu_id_to_feedback_states_to_check.at(f_id).find(dst_id) !=
344  discr_info->fu_id_to_feedback_states_to_check.at(f_id).end())
345  {
346  if(a)
347  {
348  const auto s_id = stg_info->vertex_to_state_id.at(state);
349  const std::string state_string = compute_state_string(s_id);
350 
351  result += " " + state_string +
352  ":\n"
353  " begin\n"
354  " case (" NEXT_STATE_PORT_NAME "_reg)\n";
355  }
356  const std::string state_string = compute_state_string(dst_id);
357 
358  if(not a)
359  {
360  result += ",\n";
361  }
362 
363  a = false;
364 
365  result += " " + state_string + "";
366  }
367  }
368  }
369  if(not a)
370  {
371  result += ":\n"
372  " next_to_check_prev = 1;\n"
373  " default:\n"
374  " next_to_check_prev = 0;\n"
375  " endcase\n"
376  " end\n";
377  }
378  }
379 
380  result += " default:\n"
381  " next_to_check_prev = 0;\n"
382  " endcase\n"
383  "end\n\n";
384  }
385 
386  const auto epp_val_string = [epp_trace_bitsize](size_t val) -> std::string {
387  return STR(epp_trace_bitsize) + "'d" + STR(val);
388  };
389  result += "// compute EPP increments and resets\n"
390  "always @(*)\n"
391  "begin\n\n"
392  " epp_to_reset = 0;\n"
393  " epp_increment_val = " +
394  epp_val_string(0) +
395  ";\n"
396  " epp_reset_val = " +
397  epp_val_string(0) + ";\n\n";
398 
399  std::map<unsigned int, std::map<unsigned int, size_t>> present_to_next_to_increment;
400  std::map<unsigned int, std::map<size_t, CustomOrderedSet<unsigned int>>> next_to_resetval_to_present;
401  {
402  const auto& astg = STG->CGetAstg();
403  BOOST_FOREACH(EdgeDescriptor e, boost::edges(*astg))
404  {
405  const vertex src = boost::source(e, *stg);
406  const vertex dst = boost::target(e, *stg);
407  if(src == fsm_entry_node or dst == fsm_exit_node)
408  {
409  continue;
410  }
411  const auto src_id = stg_info->vertex_to_state_id.at(src);
412  const auto dst_id = stg_info->vertex_to_state_id.at(dst);
413  const auto increment_val = eppstg->CGetTransitionInfo(e)->get_epp_increment();
414  if(increment_val != 0)
415  {
416  present_to_next_to_increment[src_id][dst_id] = increment_val;
417  }
418  }
419  for(const auto& e : discr_info->fu_id_to_reset_edges.at(f_id))
420  {
421  const vertex dst = boost::target(e, *stg);
422  const auto dst_id = stg_info->vertex_to_state_id.at(dst);
423  const auto epp_edge_from_entry = eppstg->CGetEdge(fsm_entry_node, dst);
424  const auto reset_val = eppstg->CGetTransitionInfo(epp_edge_from_entry)->get_epp_increment();
425 
426  vertex src = boost::source(e, *stg);
427  const auto src_id = stg_info->vertex_to_state_id.at(src);
428  if(stg->CGetStateInfo(src)->is_dummy)
429  {
430  THROW_ASSERT(boost::in_degree(src, *astg) == 1, "");
431  InEdgeIterator in_e_it, in_e_end;
432  boost::tie(in_e_it, in_e_end) = boost::in_edges(src, *astg);
433  src = boost::source(*in_e_it, *astg);
434  }
435  const auto epp_edge_to_exit = eppstg->CGetEdge(src, fsm_exit_node);
436  const auto increment_val = eppstg->CGetTransitionInfo(epp_edge_to_exit)->get_epp_increment();
437 
438  if(reset_val != 0)
439  {
440  next_to_resetval_to_present[dst_id][reset_val].insert(src_id);
441  }
442 
443  if(increment_val != 0)
444  {
445  present_to_next_to_increment[src_id][dst_id] = increment_val;
446  }
447  }
448  }
449 
450  THROW_ASSERT(boost::out_degree(fsm_entry_node, *stg) == 1, "");
451  OutEdgeIterator o_e_it, o_e_end;
452  boost::tie(o_e_it, o_e_end) = boost::out_edges(fsm_entry_node, *stg);
453  const std::string initial_epp_counter_str = epp_val_string((stg->CGetTransitionInfo(*o_e_it)->get_epp_increment()));
454  vertex initial_state = boost::target(*o_e_it, *stg);
455  const auto initial_state_id = stg_info->vertex_to_state_id.at(initial_state);
456  const std::string initial_state_string = compute_state_string(initial_state_id);
457 
458  // write the nested case to compute resets
459  result += " // compute the epp resets\n";
460  if(not next_to_resetval_to_present.empty())
461  {
462  result += " case (" NEXT_STATE_PORT_NAME "_reg)\n"
463  " " +
464  initial_state_string +
465  ":\n"
466  " begin\n"
467  " epp_reset_val = " +
468  initial_epp_counter_str +
469  ";\n"
470  " epp_to_reset = 1'b1;\n"
471  " end\n";
472  for(const auto& n2r2p : next_to_resetval_to_present)
473  {
474  result += " " + compute_state_string(n2r2p.first) +
475  ":\n"
476  " begin\n"
477  " case (" PRESENT_STATE_PORT_NAME "_reg)\n";
478  for(const auto& r2p : n2r2p.second)
479  {
480  const auto resetval = r2p.first;
481  bool initial = true;
482  for(const auto present : r2p.second)
483  {
484  if(initial == false)
485  {
486  result += ",\n";
487  }
488  else
489  {
490  initial = false;
491  }
492 
493  result += " " + compute_state_string(present);
494  }
495  result += ":\n"
496  " begin\n"
497  " epp_reset_val = " +
498  epp_val_string(resetval) +
499  ";\n"
500  " epp_to_reset = 1'b1;\n"
501  " end\n";
502  }
503  result += " endcase\n"
504  " end\n";
505  }
506  result += " endcase\n\n";
507  }
508  else
509  {
510  // only reset on restart
511  result += " if (" NEXT_STATE_PORT_NAME "_reg == " + initial_state_string +
512  ")\n"
513  " begin\n"
514  " epp_reset_val = " +
515  initial_epp_counter_str +
516  ";\n"
517  " epp_to_reset = 1'b1;\n"
518  " end\n\n";
519  }
520 
521  // write the nested case to compute increments
522  if(not present_to_next_to_increment.empty())
523  {
524  result += " // nested case to compute epp increments\n"
525  " case (" PRESENT_STATE_PORT_NAME "_reg)\n";
526  for(const auto& p2n2i : present_to_next_to_increment)
527  {
528  result += " " + compute_state_string(p2n2i.first) +
529  ":\n"
530  " begin\n"
531  " case (" NEXT_STATE_PORT_NAME "_reg)\n";
532  for(const auto& n2i : p2n2i.second)
533  {
534  const auto next_id = n2i.first;
535  const auto increment = n2i.second;
536  result += " " + compute_state_string(next_id) +
537  ":\n"
538  " begin\n"
539  " epp_increment_val = " +
540  epp_val_string(increment) +
541  ";\n"
542  " end\n";
543  }
544  result += " endcase\n"
545  " end\n";
546  }
547  result += " endcase\n";
548  }
549 
550  result += "end\n\n";
551 
552  result += "always @(posedge " CLOCK_PORT_NAME ")\n"
553  "begin\n"
554  " epp_trace_reg <= epp_trace_memory[next_epp_trace_offset];\n"
555  "end\n\n";
556 
557  const auto reset_type = HLSMgr->get_parameter()->getOption<std::string>(OPT_reset_type);
558  if(reset_type == "no" || reset_type == "sync")
559  {
560  result += "always @(posedge " CLOCK_PORT_NAME ")\n";
561  }
562  else if(!HLSMgr->get_parameter()->getOption<bool>(OPT_reset_level))
563  {
564  result += "always @(posedge " CLOCK_PORT_NAME " or negedge " RESET_PORT_NAME ")\n";
565  }
566  else
567  {
568  result += "always @(posedge " CLOCK_PORT_NAME " or posedge " RESET_PORT_NAME ")\n";
569  }
570 
571  if(!HLSMgr->get_parameter()->getOption<bool>(OPT_reset_level))
572  {
573  result += "if (" RESET_PORT_NAME " == 1'b0)\n";
574  }
575  else
576  {
577  result += "if (" RESET_PORT_NAME " == 1'b1)\n";
578  }
579 
580  result += " begin\n"
581  " prev_epp_counter <= 0;\n"
582  " epp_counter <= 0;\n"
583  " epp_trace_offset <= 0;\n"
584  " prev_epp_trace_offset <= 0;\n"
585  " to_check_prev <= 0;\n"
586  " checker_state <= 0;\n"
587  " if (EPP_TRACE_METADATA_BITSIZE > 0)\n"
588  " begin\n"
589  " decremented_metadata_reg <= EPP_TRACE_INITIAL_METADATA;\n"
590  " trace_offset_increment_compressed_reg <= 0;\n"
591  " end\n"
592  "end\n"
593  "else\n"
594  "begin\n"
595  " if (trace_offset_increment)\n"
596  " begin\n"
597  " prev_epp_trace_offset <= epp_trace_offset;\n"
598  " prev_data <= trace_data;\n"
599  " end\n"
600  " prev_epp_counter <= epp_incremented_counter;\n"
601  " epp_counter <= next_epp_counter;\n"
602  " epp_trace_offset <= next_epp_trace_offset;\n"
603  " to_check_prev <= next_to_check_prev;\n"
604  " checker_state <= next_checker_state;\n"
605  " if (EPP_TRACE_METADATA_BITSIZE > 0)\n"
606  " begin\n"
607  " decremented_metadata_reg <= decremented_metadata;\n"
608  " trace_offset_increment_compressed_reg <= trace_offset_increment_compressed;\n"
609  " end\n"
610  "end\n"
611  "end\n"
612  "else\n"
613  "begin\n"
614  " assign out_mismatch = 0;\n"
615  " assign out_mismatch_id = 0;\n"
616  " assign out_mismatch_trace_offset = 0;\n"
617  "end\n"
618  "endgenerate\n\n";
619 
620  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Added control flow checker..." + result);
621  return result;
622 }
623 
625 {
629 
630  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Start adding clock signal...");
632  structural_objectRef clock_obj = SM->add_port(CLOCK_PORT_NAME, port_o::IN, circuit, port_type);
633  GetPointer<port_o>(clock_obj)->set_is_clock(true);
635  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Clock signal added!");
636 
637  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Start adding reset signal...");
639  SM->add_port(RESET_PORT_NAME, port_o::IN, circuit, port_type);
640  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Reset signal added!");
641 }
642 
644 {
648  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Start adding Done signal...");
650  SM->add_port(DONE_PORT_NAME, port_o::IN, circuit, port_type);
651  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Done signal added!");
652 }
653 
655 {
659  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Start adding start signal...");
661  SM->add_port(START_PORT_NAME, port_o::IN, circuit, port_type);
662  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - Start signal added!");
663 }
664 
665 void ControlFlowChecker::add_present_state(structural_objectRef circuit, unsigned int state_bitsize)
666 {
670  structural_type_descriptorRef(new structural_type_descriptor("bool", state_bitsize));
671  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Adding present/next state signals...");
673  SM->add_port(PRESENT_STATE_PORT_NAME, port_o::IN, circuit, port_type);
674  SM->add_port(NEXT_STATE_PORT_NAME, port_o::IN, circuit, port_type);
675  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - present/next state signals added!");
676 }
677 
679 {
680  const auto curr_address_bitsize = HLSMgr->get_address_bitsize();
683  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, " * Adding notifier signals...");
685  structural_objectRef pm = SM->add_port(NOTIFIER_PORT_MISMATCH, port_o::OUT, circuit,
687  GetPointer<port_o>(pm)->set_is_memory(true);
689  SM->add_port(NOTIFIER_PORT_MISMATCH_ID, port_o::OUT, circuit,
690  structural_type_descriptorRef(new structural_type_descriptor("bool", curr_address_bitsize)));
691  GetPointer<port_o>(pmi)->set_is_memory(true);
693  SM->add_port(NOTIFIER_PORT_MISMATCH_OFFSET, port_o::OUT, circuit,
694  structural_type_descriptorRef(new structural_type_descriptor("bool", curr_address_bitsize)));
695  GetPointer<port_o>(pmo)->set_is_memory(true);
696  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, " - notifier signals added!");
697 }
698 
699 void ControlFlowChecker::add_common_ports(structural_objectRef circuit, unsigned int state_bitsize)
700 {
701  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Adding clock and reset ports...");
702  add_clock_reset(circuit);
703 
704  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Adding the start port...");
705  add_start_port(circuit);
706 
707  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Adding the done port...");
708  add_done_port(circuit);
709 
710  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Adding the present_state...");
711  add_present_state(circuit, state_bitsize);
712 
713  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Adding notifiers...");
714  add_notifiers(circuit);
715 }
716 
718 {
719  const HWDiscrepancyInfoConstRef discr_info = HLSMgr->RDiscr->hw_discrepancy_info;
720  if(discr_info->fu_id_control_flow_skip.find(funId) != discr_info->fu_id_control_flow_skip.end())
721  {
723  }
725  const FunctionBehaviorConstRef FB = HLSMgr->CGetFunctionBehavior(funId);
726  const std::string f_name = FB->CGetBehavioralHelper()->get_function_name();
727  const std::string cfc_module_name = "control_flow_checker_" + f_name;
728  structural_type_descriptorRef module_type =
730  HLS->control_flow_checker->set_top_info("ControlFlowChecker_i", module_type);
732  GetPointer<module>(checker_circuit)->set_description("Control Flow Checker for " + f_name);
733  GetPointer<module>(checker_circuit)->set_copyright(GENERATED_COPYRIGHT);
734  GetPointer<module>(checker_circuit)->set_authors("Checker automatically generated by bambu");
735  GetPointer<module>(checker_circuit)->set_license(GENERATED_LICENSE);
736  const auto one_hot_encoding = IsOneHotFSM(funId, HLSMgr);
737 
738  const auto& stg = HLS->STG->CGetStg();
739  const auto& stg_info = stg->CGetStateTransitionGraphInfo();
740  unsigned max_value = 0;
741  for(const auto& s : stg_info->state_id_to_vertex)
742  {
743  max_value = std::max(max_value, s.first);
744  }
745  const unsigned int state_bitsize = comp_state_bitsize(one_hot_encoding, HLSMgr, funId, max_value);
746 
747  size_t epp_trace_bitsize = discr_info->fu_id_to_epp_trace_bitsize.at(funId);
748  GetPointer<module>(checker_circuit)->AddParameter("STATE_BITSIZE", STR(state_bitsize));
749  GetPointer<module>(checker_circuit)->AddParameter("EPP_TRACE_BITSIZE", STR(epp_trace_bitsize));
750  GetPointer<module>(checker_circuit)->AddParameter("EPP_TRACE_METADATA_BITSIZE", "0");
751  GetPointer<module>(checker_circuit)->AddParameter("MEMORY_INIT_file", GetPath("trace.mem"));
752  GetPointer<module>(checker_circuit)->AddParameter("EPP_TRACE_LENGTH", "0");
753  GetPointer<module>(checker_circuit)->AddParameter("EPP_MISMATCH_ID", "0");
754  GetPointer<module>(checker_circuit)->AddParameter("EPP_TRACE_INITIAL_METADATA", "0");
755 
756  add_common_ports(checker_circuit, state_bitsize);
757 
759  checker_circuit, NP_functionality::LIBRARY,
760  cfc_module_name +
761  " out_mismatch out_mismatch_id out_mismatch_trace_offset STATE_BITSIZE EPP_TRACE_BITSIZE "
762  "EPP_TRACE_METADATA_BITSIZE EPP_TRACE_INITIAL_METADATA MEMORY_INIT_file EPP_TRACE_LENGTH EPP_MISMATCH_ID");
763 
764  std::string verilog_cf_checker_description = create_control_flow_checker(
765  epp_trace_bitsize, funId, HLS->STG, HLSMgr, discr_info, one_hot_encoding, max_value, state_bitsize, debug_level);
767  verilog_cf_checker_description);
769 }
#define PRESENT_STATE_PORT_NAME
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
const HLS_managerRef HLSMgr
information about all the HLS synthesis
Definition: hls_step.hpp:205
Data structure representing the entire HLS information.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
refcount< structural_type_descriptor > structural_type_descriptorRef
RefCount type definition of the structural_type_descriptor class structure.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define NEXT_STATE_PORT_NAME
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define START_PORT_NAME
This file contains the structures needed to manage a graph that will represent the state transition g...
Structure representing the most relevant information about the type of a structural object...
const ParameterConstRef Param
class containing all the parameters
Definition: hls.hpp:169
string target
Definition: lenet_tvm.py:16
static std::string create_control_flow_checker(size_t epp_trace_bitsize, const unsigned int f_id, const StateTransitionGraphManagerRef &STG, const HLS_managerRef HLSMgr, const HWDiscrepancyInfoConstRef &discr_info, bool one_hot_encoding, unsigned max_value, unsigned int state_bitsize, int DEBUG_PARAMETER(debug_level))
#define GET_CLASS(obj)
Macro returning the actual type of an object.
std::string get_function_name() const
Return the name of the function.
#define GENERATED_LICENSE
const StateTransitionGraphConstRef CGetEPPStg() const
Returns pointer to acyclic STG with additional edges for Efficient Path Profiling.
const structural_objectRef get_circ() const
Get a reference to circ field.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
ControlFlowChecker(const ParameterConstRef Param, const HLS_managerRef HLSMgr, unsigned int funId, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
const unsigned int funId
identifier of the function to be processed (0 means that it is a global step)
This class manages the circuit structures.
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
Definition: graph.hpp:1310
static bool IsOneHotFSM(unsigned int function_id, const HLS_managerRef HLSMgr)
redefinition of map to manage ordered/unordered structures
void add_start_port(structural_objectRef circuit)
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
#define CLOCK_PORT_NAME
standard name for ports
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
~ControlFlowChecker() override
Destructor.
void add_common_ports(structural_objectRef circuit, unsigned int state_bitsize)
static void add_NP_functionality(structural_objectRef cir, NP_functionality::NP_functionaly_type dt, std::string functionality_description)
Add a not-parsed functionality.
unsigned edges[4545]
Definition: graph.h:25
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
#define DONE_PORT_NAME
HLSFlowStep_Type
Definition: hls_step.hpp:95
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
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.
redefinition of set to manage ordered/unordered structures
void add_present_state(structural_objectRef circuit, unsigned int state_bitsize)
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
utility function used to read files.
This file contains the structures needed to manage a graph that will represent the state transition g...
const BehavioralHelperConstRef CGetBehavioralHelper() const
Returns the helper associated with the function.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This file collects some utility functions and macros.
const CustomUnorderedSet< std::tuple< HLSFlowStep_Type, HLSFlowStepSpecializationConstRef, HLSFlowStep_Relationship > > ComputeHLSRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
refcount< structural_manager > structural_managerRef
RefCount type definition of the structural_manager class structure.
int result[SIZE]
Definition: adpcm.c:800
const StateTransitionGraphConstRef CGetAstg() const
Returns pointer to state transition graph created.
void add_clock_reset(structural_objectRef circuit)
DesignFlowStep_Status InternalExec() override
Execute the step.
#define NOTIFIER_PORT_MISMATCH
static unsigned int comp_state_bitsize(bool one_hot_encoding, const HLS_managerRef HLSMgr, const unsigned int f_id, unsigned max_value)
structural_managerRef control_flow_checker
Store the description of the control flow checker.
Definition: hls.hpp:161
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
static unsigned int bitnumber(unsigned long long n)
Counts the number of bits in an unsigned int.
hlsRef HLS
HLS data structure of the function to be analyzed.
#define NOTIFIER_PORT_MISMATCH_OFFSET
void add_done_port(structural_objectRef circuit)
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
It collects all the common strings covering PandA copyrights issues.
#define DEBUG_PARAMETER(parameter)
macro used to solve problem of parameters used only in not-release
Definition: utility.hpp:91
this class is used to manage the command-line or XML options.
#define RESET_PORT_NAME
Class implementation of the structural_manager.
StateTransitionGraphManagerRef STG
Store the refcounted state transition graph.
Definition: hls.hpp:124
int debug_level
The debug level.
void add_notifiers(structural_objectRef circuit)
Data structure definition for high-level synthesis flow.
Superclass include.
const StateTransitionGraphConstRef CGetStg() const
Returns pointer to state transition graph created.
#define GENERATED_COPYRIGHT
HLS specialization of generic_device.
A brief description of the C++ Header File.
#define NOTIFIER_PORT_MISMATCH_ID
boost::graph_traits< graph >::edge_descriptor EdgeDescriptor
edge definition.
Definition: graph.hpp:1316
#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:53 for PandA-2024.02 by doxygen 1.8.13