55 #include <boost/algorithm/string/case_conv.hpp> 63 unsigned int _funId,
const DesignFlowManagerConstRef _design_flow_manager)
75 switch(relationship_type)
99 const auto vendor = [&]() -> std::string {
100 const auto tgt_device = HLSMgr->get_HLS_device();
101 if(tgt_device->has_parameter(
"vendor"))
103 return tgt_device->get_parameter<std::string>(
"vendor");
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))
120 unsigned int n_states = HLSMgr->get_HLS(f_id)->STG->get_number_of_states();
122 if(max_value != n_states - 1)
127 unsigned int state_bitsize = one_hot_encoding ? (max_value + 1) : bitsnumber;
129 return state_bitsize;
135 unsigned max_value,
unsigned int state_bitsize,
140 const auto& stg = STG->
CGetStg();
141 const auto& stg_info = stg->CGetStateTransitionGraphInfo();
144 "parameter METADATA_BITS_HELPER_SIZE = (EPP_TRACE_METADATA_BITSIZE > 0) ? EPP_TRACE_METADATA_BITSIZE : 1;\n" 146 "if(EPP_TRACE_LENGTH>0)\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" 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" 210 " " NEXT_STATE_PORT_NAME
"_reg <= " NEXT_STATE_PORT_NAME
";\n" 213 result +=
"initial\n" 215 " $readmemb(MEMORY_INIT_file, epp_trace_memory, 0, EPP_TRACE_LENGTH-1);\n" 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";
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" 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" 232 " assign trace_data = epp_trace_reg;\n" 233 " assign trace_offset_increment_compressed = trace_offset_increment;\n" 235 "assign next_epp_trace_offset = epp_trace_offset + trace_offset_increment_compressed;\n\n";
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";
245 result +=
"// synthesis translate_off\n" 248 " if (out_mismatch)\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" 256 "// synthesis translate_on\n";
258 result +=
"// update state of the checker\n" 261 " next_checker_state = checker_state;\n" 262 " case (checker_state)\n" 265 " if (" START_PORT_NAME
"_reg && ! " DONE_PORT_NAME
"_reg)\n" 266 " next_checker_state = 1;\n" 270 " if (" DONE_PORT_NAME
"_reg)\n" 271 " next_checker_state = 0;\n" 274 " next_checker_state = 0;\n" 279 const auto encode_one_hot = [](
unsigned int nstates,
unsigned int val) -> std::string {
281 for(
unsigned int i = 0; i < nstates; ++i)
283 res = (val == i ?
"1" :
"0") + res;
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));
295 result +=
"// compute if this state is to check\n" 298 " case (" PRESENT_STATE_PORT_NAME
"_reg)";
300 bool is_first =
true;
301 for(
const auto s_id : discr_info->fu_id_to_states_to_check.at(f_id))
303 const std::string state_string = compute_state_string(s_id);
308 result +=
"\n " + state_string;
313 " to_check_now = 1;\n";
315 result +=
" default:\n" 316 " to_check_now = 0;\n" 321 const auto fsm_entry_node = stg_info->entry_node;
322 const auto fsm_exit_node = stg_info->exit_node;
325 result +=
"// compute if at the next cycle we have to check the previous state\n" 328 " case (" PRESENT_STATE_PORT_NAME
"_reg)\n";
330 BOOST_FOREACH(
vertex state, boost::vertices(*stg))
332 if(state == fsm_entry_node or state == fsm_exit_node)
337 BOOST_FOREACH(
EdgeDescriptor out_edge, boost::out_edges(state, *stg))
339 if(stg->GetSelector(out_edge) & TransitionInfo::StateTransitionType::ST_EDGE_FEEDBACK)
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())
348 const auto s_id = stg_info->vertex_to_state_id.at(state);
349 const std::string state_string = compute_state_string(s_id);
351 result +=
" " + state_string +
354 " case (" NEXT_STATE_PORT_NAME
"_reg)\n";
356 const std::string state_string = compute_state_string(dst_id);
365 result +=
" " + state_string +
"";
372 " next_to_check_prev = 1;\n" 374 " next_to_check_prev = 0;\n" 380 result +=
" default:\n" 381 " next_to_check_prev = 0;\n" 386 const auto epp_val_string = [epp_trace_bitsize](
size_t val) -> std::string {
387 return STR(epp_trace_bitsize) +
"'d" +
STR(val);
389 result +=
"// compute EPP increments and resets\n" 392 " epp_to_reset = 0;\n" 393 " epp_increment_val = " +
396 " epp_reset_val = " +
397 epp_val_string(0) +
";\n\n";
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;
405 const vertex src = boost::source(e, *stg);
407 if(src == fsm_entry_node or dst == fsm_exit_node)
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)
416 present_to_next_to_increment[src_id][dst_id] = increment_val;
419 for(
const auto& e : discr_info->fu_id_to_reset_edges.at(f_id))
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();
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)
432 boost::tie(in_e_it, in_e_end) = boost::in_edges(src, *astg);
433 src = boost::source(*in_e_it, *astg);
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();
440 next_to_resetval_to_present[dst_id][reset_val].insert(src_id);
443 if(increment_val != 0)
445 present_to_next_to_increment[src_id][dst_id] = increment_val;
450 THROW_ASSERT(boost::out_degree(fsm_entry_node, *stg) == 1,
"");
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()));
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);
459 result +=
" // compute the epp resets\n";
460 if(not next_to_resetval_to_present.empty())
462 result +=
" case (" NEXT_STATE_PORT_NAME
"_reg)\n" 464 initial_state_string +
467 " epp_reset_val = " +
468 initial_epp_counter_str +
470 " epp_to_reset = 1'b1;\n" 472 for(
const auto& n2r2p : next_to_resetval_to_present)
474 result +=
" " + compute_state_string(n2r2p.first) +
477 " case (" PRESENT_STATE_PORT_NAME
"_reg)\n";
478 for(
const auto& r2p : n2r2p.second)
480 const auto resetval = r2p.first;
482 for(
const auto present : r2p.second)
493 result +=
" " + compute_state_string(present);
497 " epp_reset_val = " +
498 epp_val_string(resetval) +
500 " epp_to_reset = 1'b1;\n" 503 result +=
" endcase\n" 506 result +=
" endcase\n\n";
511 result +=
" if (" NEXT_STATE_PORT_NAME
"_reg == " + initial_state_string +
514 " epp_reset_val = " +
515 initial_epp_counter_str +
517 " epp_to_reset = 1'b1;\n" 522 if(not present_to_next_to_increment.empty())
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)
528 result +=
" " + compute_state_string(p2n2i.first) +
531 " case (" NEXT_STATE_PORT_NAME
"_reg)\n";
532 for(
const auto& n2i : p2n2i.second)
534 const auto next_id = n2i.first;
535 const auto increment = n2i.second;
536 result +=
" " + compute_state_string(next_id) +
539 " epp_increment_val = " +
540 epp_val_string(increment) +
544 result +=
" endcase\n" 547 result +=
" endcase\n";
554 " epp_trace_reg <= epp_trace_memory[next_epp_trace_offset];\n" 557 const auto reset_type = HLSMgr->get_parameter()->getOption<std::string>(OPT_reset_type);
558 if(reset_type ==
"no" || reset_type ==
"sync")
562 else if(!HLSMgr->get_parameter()->getOption<
bool>(OPT_reset_level))
571 if(!HLSMgr->get_parameter()->getOption<
bool>(OPT_reset_level))
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" 589 " decremented_metadata_reg <= EPP_TRACE_INITIAL_METADATA;\n" 590 " trace_offset_increment_compressed_reg <= 0;\n" 595 " if (trace_offset_increment)\n" 597 " prev_epp_trace_offset <= epp_trace_offset;\n" 598 " prev_data <= trace_data;\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" 607 " decremented_metadata_reg <= decremented_metadata;\n" 608 " trace_offset_increment_compressed_reg <= trace_offset_increment_compressed;\n" 614 " assign out_mismatch = 0;\n" 615 " assign out_mismatch_id = 0;\n" 616 " assign out_mismatch_trace_offset = 0;\n" 633 GetPointer<port_o>(clock_obj)->set_is_clock(
true);
680 const auto curr_address_bitsize = HLSMgr->get_address_bitsize();
687 GetPointer<port_o>(pm)->set_is_memory(
true);
691 GetPointer<port_o>(pmi)->set_is_memory(
true);
695 GetPointer<port_o>(pmo)->set_is_memory(
true);
720 if(discr_info->fu_id_control_flow_skip.find(
funId) != discr_info->fu_id_control_flow_skip.end())
727 const std::string cfc_module_name =
"control_flow_checker_" + f_name;
732 GetPointer<module>(checker_circuit)->set_description(
"Control Flow Checker for " + f_name);
734 GetPointer<module>(checker_circuit)->set_authors(
"Checker automatically generated by bambu");
739 const auto& stg_info = stg->CGetStateTransitionGraphInfo();
740 unsigned max_value = 0;
741 for(
const auto& s : stg_info->state_id_to_vertex)
743 max_value =
std::max(max_value, s.first);
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");
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");
765 epp_trace_bitsize,
funId,
HLS->
STG, HLSMgr, discr_info, one_hot_encoding, max_value, state_bitsize,
debug_level);
767 verilog_cf_checker_description);
#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
Data structure representing the entire HLS information.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
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.
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
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.
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 CLOCK_PORT_NAME
standard name for ports
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
~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.
void set_top_info(const std::string &id, const technology_managerRef &LM, const std::string &Library="")
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.
Target must be reexecuted.
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.
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.
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.
std::string GetPath(std::filesystem::path path)
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...
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
this class is used to manage the command-line or XML options.
Class implementation of the structural_manager.
StateTransitionGraphManagerRef STG
Store the refcounted state transition graph.
int debug_level
The debug level.
void add_notifiers(structural_objectRef circuit)
Data structure definition for high-level synthesis flow.
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.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...