62 #define BURST_TYPE_STR(type) std::string(type == 0 ? "FIXED" : (type == 1 ? "INCREMENTAL" : "UNKNOWN")) 134 const std::vector<ModuleGenerator::parameter>& ,
135 const std::vector<ModuleGenerator::parameter>& _ports_in,
136 const std::vector<ModuleGenerator::parameter>& _ports_out,
137 const std::vector<ModuleGenerator::parameter>& )
149 const auto top_fid = HLSMgr->CGetCallGraphManager()->GetRootFunction(function_id);
150 const auto top_fname = HLSMgr->CGetFunctionBehavior(top_fid)->CGetBehavioralHelper()->GetMangledFunctionName();
151 const auto& iface_attrs = HLSMgr->module_arch->GetArchitecture(top_fname)->ifaces.at(bundle_name);
153 const auto Param = HLSMgr->get_parameter();
154 const auto has_requested_burst_type = Param->isOption(OPT_axi_burst_type);
155 unsigned int axi_burst_type = has_requested_burst_type ? Param->getOption<
unsigned int>(OPT_axi_burst_type) : 0
U;
157 const auto hls_d = HLSMgr->get_HLS_device();
158 const auto has_device_burst_type = hls_d->has_parameter(
"axi_burst_type");
159 const auto device_burst_type = has_device_burst_type ? hls_d->get_parameter<
unsigned int>(
"axi_burst_type") : 0
U;
160 if(has_device_burst_type)
162 if(has_requested_burst_type && axi_burst_type != device_burst_type)
164 THROW_WARNING(
"Requested AXI burst type conflicts with selected device supported AXI burst type: " +
167 axi_burst_type = device_burst_type;
171 unsigned long long line_count = 0;
172 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_line_count); it != iface_attrs.end())
174 line_count = std::stoull(it->second);
177 out <<
"localparam BITSIZE_address=BITSIZE_" << _ports_in[
i_in4].name <<
",\n" 178 <<
" BITSIZE_bus=" << _ports_out[
o_wdata].type_size <<
",\n" 179 <<
" BITSIZE_bus_size=BITSIZE_bus/8,\n" 180 <<
" BITSIZE_data=BITSIZE_" << _ports_in[
i_in3].name <<
",\n" 181 <<
" BITSIZE_data_size=BITSIZE_data/8,\n" 182 <<
" BITSIZE_awlen=" << _ports_out[
o_awlen].type_size <<
",\n" 183 <<
" BITSIZE_arlen=" << _ports_out[
o_arlen].type_size <<
",\n" 184 <<
" BITSIZE_awid=" << _ports_out[
o_awid].type_size <<
",\n" 185 <<
" BITSIZE_arid=" << _ports_out[
o_arid].type_size <<
",\n" 186 <<
" BITSIZE_bid=" << _ports_in[
i_bid].type_size <<
",\n" 187 <<
" BITSIZE_rid=" << _ports_in[
i_rid].type_size <<
";\n\n";
189 function automatic integer log2; 191 `ifdef _SIM_HAVE_CLOG2 192 log2 = $clog2(value); 194 automatic integer temp_value = value-1; 195 for (log2=0; temp_value > 0; log2=log2+1) 196 temp_value = temp_value >> 1; 203 std::string ip_components;
206 ip_components =
"MinimalAXI4AdapterSingleBeat";
207 out <<
"MinimalAXI4AdapterSingleBeat #(.BURST_TYPE(" << axi_burst_type <<
"),\n" 208 <<
" .BITSIZE_Mout_addr_ram(BITSIZE_address),\n" 209 <<
" .BITSIZE_Mout_Wdata_ram(BITSIZE_data),\n" 210 <<
" .BITSIZE_Mout_data_ram_size(BITSIZE_" << _ports_in[
i_in2].name <<
"),\n" 211 <<
" .BITSIZE_M_Rdata_ram(BITSIZE_data),\n" 212 <<
" .BITSIZE_m_axi_awid(BITSIZE_awid),\n" 213 <<
" .BITSIZE_m_axi_awaddr(BITSIZE_address),\n" 214 <<
" .BITSIZE_m_axi_awlen(BITSIZE_awlen),\n" 215 <<
" .BITSIZE_m_axi_wdata(BITSIZE_bus),\n" 216 <<
" .BITSIZE_m_axi_wstrb(BITSIZE_bus_size),\n" 217 <<
" .BITSIZE_m_axi_bid(BITSIZE_bid),\n" 218 <<
" .BITSIZE_m_axi_arid(BITSIZE_arid),\n" 219 <<
" .BITSIZE_m_axi_araddr(BITSIZE_address),\n" 220 <<
" .BITSIZE_m_axi_arlen(BITSIZE_arlen),\n" 221 <<
" .BITSIZE_m_axi_rid(BITSIZE_rid),\n" 222 <<
" .BITSIZE_m_axi_rdata(BITSIZE_bus)) adapter (.M_DataRdy(done_port),\n" 223 <<
" .M_Rdata_ram(" << _ports_out[
o_out1].name <<
"),\n" 224 <<
" .m_axi_arid(" << _ports_out[
o_arid].name <<
"),\n" 225 <<
" .m_axi_araddr(" << _ports_out[
o_araddr].name <<
"),\n" 226 <<
" .m_axi_arlen(" << _ports_out[
o_arlen].name <<
"),\n" 227 <<
" .m_axi_arsize(" << _ports_out[
o_arsize].name <<
"),\n" 228 <<
" .m_axi_arburst(" << _ports_out[
o_arburst].name <<
"),\n" 229 <<
" .m_axi_arlock(" << _ports_out[
o_arlock].name <<
"),\n" 230 <<
" .m_axi_arcache(" << _ports_out[
o_arcache].name <<
"),\n" 231 <<
" .m_axi_arprot(" << _ports_out[
o_arprot].name <<
"),\n" 232 <<
" .m_axi_arqos(" << _ports_out[
o_arqos].name <<
"),\n" 233 <<
" .m_axi_arregion(" << _ports_out[
o_arregion].name <<
"),\n" 234 <<
" .m_axi_aruser(" << _ports_out[
o_aruser].name <<
"),\n" 235 <<
" .m_axi_arvalid(" << _ports_out[
o_arvalid].name <<
"),\n" 236 <<
" .m_axi_rready(" << _ports_out[
o_rready].name <<
"),\n" 237 <<
" .m_axi_awid(" << _ports_out[
o_awid].name <<
"),\n" 238 <<
" .m_axi_awaddr(" << _ports_out[
o_awaddr].name <<
"),\n" 239 <<
" .m_axi_awlen(" << _ports_out[
o_awlen].name <<
"),\n" 240 <<
" .m_axi_awsize(" << _ports_out[
o_awsize].name <<
"),\n" 241 <<
" .m_axi_awburst(" << _ports_out[
o_awburst].name <<
"),\n" 242 <<
" .m_axi_awlock(" << _ports_out[
o_awlock].name <<
"),\n" 243 <<
" .m_axi_awcache(" << _ports_out[
o_awcache].name <<
"),\n" 244 <<
" .m_axi_awprot(" << _ports_out[
o_awprot].name <<
"),\n" 245 <<
" .m_axi_awqos(" << _ports_out[
o_awqos].name <<
"),\n" 246 <<
" .m_axi_awregion(" << _ports_out[
o_awregion].name <<
"),\n" 247 <<
" .m_axi_awuser(" << _ports_out[
o_awuser].name <<
"),\n" 248 <<
" .m_axi_awvalid(" << _ports_out[
o_awvalid].name <<
"),\n" 249 <<
" .m_axi_wdata(" << _ports_out[
o_wdata].name <<
"),\n" 250 <<
" .m_axi_wstrb(" << _ports_out[
o_wstrb].name <<
"),\n" 251 <<
" .m_axi_wlast(" << _ports_out[
o_wlast].name <<
"),\n" 252 <<
" .m_axi_wuser(" << _ports_out[
o_wuser].name <<
"),\n" 253 <<
" .m_axi_wvalid(" << _ports_out[
o_wvalid].name <<
"),\n" 254 <<
" .m_axi_bready(" << _ports_out[
o_bready].name <<
"),\n" 255 <<
" .clock(clock),\n" 256 <<
" .reset(reset),\n" 257 <<
" .Mout_oe_ram(" << _ports_in[
i_start].name <<
" && !" << _ports_in[
i_in1].name <<
"),\n" 258 <<
" .Mout_we_ram(" << _ports_in[
i_start].name <<
" && " << _ports_in[
i_in1].name <<
"),\n" 259 <<
" .Mout_addr_ram(" << _ports_in[
i_in4].name <<
"),\n" 260 <<
" .Mout_Wdata_ram(" << _ports_in[
i_in3].name <<
"),\n" 261 <<
" .Mout_data_ram_size(" << _ports_in[
i_in2].name <<
"),\n" 262 <<
" .m_axi_arready(" << _ports_in[
i_arready].name <<
"),\n" 263 <<
" .m_axi_rid(" << _ports_in[
i_rid].name <<
"),\n" 264 <<
" .m_axi_rdata(" << _ports_in[
i_rdata].name <<
"),\n" 265 <<
" .m_axi_rresp(" << _ports_in[
i_rresp].name <<
"),\n" 266 <<
" .m_axi_rlast(" << _ports_in[
i_rlast].name <<
"),\n" 267 <<
" .m_axi_rvalid(" << _ports_in[
i_rvalid].name <<
"),\n" 268 <<
" .m_axi_awready(" << _ports_in[
i_awready].name <<
"),\n" 269 <<
" .m_axi_wready(" << _ports_in[
i_wready].name <<
"),\n" 270 <<
" .m_axi_bid(" << _ports_in[
i_bid].name <<
"),\n" 271 <<
" .m_axi_bresp(" << _ports_in[
i_bresp].name <<
"),\n" 272 <<
" .m_axi_bvalid(" << _ports_in[
i_bvalid].name <<
"));\n";
276 const auto line_off_w = std::to_string(
ceil_log2(line_count));
277 std::string word_off_w =
"1";
278 std::string be_data_w = std::to_string(_ports_out[
o_wdata].type_size);
279 std::string n_ways =
"1";
280 unsigned long long wtbuf_depth_w = 2ULL;
281 std::string rep_policy =
"0";
282 std::string write_pol =
"0";
284 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_line_size); it != iface_attrs.end())
286 word_off_w = std::to_string(
ceil_log2(std::stoull(it->second)));
288 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_bus_size); it != iface_attrs.end())
290 be_data_w = it->second;
292 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_ways); it != iface_attrs.end())
296 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_num_write_outstanding); it != iface_attrs.end())
298 wtbuf_depth_w =
ceil_log2(std::stoull(it->second));
299 if(wtbuf_depth_w < 1)
304 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_rep_policy); it != iface_attrs.end())
306 const auto rp_name = boost::to_upper_copy(it->second);
311 else if(rp_name ==
"MRU")
315 else if(rp_name ==
"TREE")
321 THROW_ERROR(
"Unexpected cache replacement policy: " + it->second);
324 if(
auto it = iface_attrs.find(FunctionArchitecture::iface_cache_write_policy); it != iface_attrs.end())
326 const auto wp_name = boost::to_upper_copy(it->second);
331 else if(wp_name ==
"WB")
337 THROW_ERROR(
"Unexpected cache write policy: " + it->second);
341 ip_components =
"IOB_cache_axi";
342 out <<
"wire [BITSIZE_address-1:log2(BITSIZE_data_size)] addr;\n" 343 <<
"wire [BITSIZE_data_size-1:0] wstrb;\n" 344 <<
"wire [BITSIZE_data-1:0] rdata;\n" 347 <<
"reg state, state_next;\n\n";
349 out <<
"localparam S_IDLE = 0, S_FLUSH = 1;\n" 350 <<
"initial state = S_IDLE;\n\n" 351 <<
"assign " << _ports_out[
o_aruser].name <<
" = 0;\n" 352 <<
"assign " << _ports_out[
o_arregion].name <<
" = 0;\n" 353 <<
"assign " << _ports_out[
o_wuser].name <<
" = 0;\n" 354 <<
"assign " << _ports_out[
o_awuser].name <<
" = 0;\n" 355 <<
"assign " << _ports_out[
o_awregion].name <<
" = 0;\n\n" 356 <<
"assign done_port = state == S_IDLE? ready : !dirty;\n" 357 <<
"assign addr = " << _ports_in[
i_in4].name <<
"[BITSIZE_address-1:log2(BITSIZE_data_size)];\n" 358 <<
"assign wstrb = " << _ports_in[
i_in1].name <<
" ? (1 << (" << _ports_in[
i_in2].name <<
"/8)) - 1 : 0;\n" 359 <<
"assign " << _ports_out[
o_out1].name <<
" = done_port ? rdata : 0;\n\n" 360 <<
"always @(*) begin\n" 361 <<
" state_next = state;\n" 362 <<
" if(state == S_IDLE) begin\n" 363 <<
" if(" << _ports_in[
i_start].name <<
" && " << _ports_in[
i_in1].name <<
" && " << _ports_in[
i_in2].name
365 <<
" state_next = S_FLUSH;\n" 367 <<
" end else if(state == S_FLUSH) begin\n" 368 <<
" if(!dirty) begin\n" 369 <<
" state_next = S_IDLE;\n" 373 <<
"always @(posedge clock 1RESET_EDGE) begin\n" 374 <<
" state <= state_next;\n" 375 <<
" if(1RESET_VALUE) begin\n" 376 <<
" state <= S_IDLE;\n" 391 `elsif XILINX_SIMULATOR 400 out << "IOB_cache_axi #(.FE_ADDR_W(BITSIZE_address),\n" 401 <<
" .BE_ADDR_W(BITSIZE_address),\n" 402 <<
" .BE_DATA_W(" << be_data_w <<
"),\n" 403 <<
" .N_WAYS(" << n_ways <<
"),\n" 404 <<
" .LINE_OFF_W(" << line_off_w <<
"),\n" 405 <<
" .WORD_OFF_W(" << word_off_w <<
"),\n" 406 <<
" .WTBUF_DEPTH_W(" << wtbuf_depth_w <<
"),\n" 407 <<
" .REP_POLICY(" << rep_policy <<
"),\n" 408 <<
" .WRITE_POL(" << write_pol <<
"),\n" 410 <<
" .CTRL_CACHE(`_CACHE_CNT),\n" 411 <<
" .CTRL_CNT(`_CACHE_CNT),\n" 412 <<
" .BURST_TYPE(" << axi_burst_type <<
"),\n" 413 <<
" .BITSIZE_addr(BITSIZE_address-log2(BITSIZE_data_size)),\n" 414 <<
" .BITSIZE_wdata(BITSIZE_data),\n" 415 <<
" .BITSIZE_wstrb(BITSIZE_data_size),\n" 416 <<
" .BITSIZE_rdata(BITSIZE_data),\n" 417 <<
" .BITSIZE_m_axi_awid(BITSIZE_awid),\n" 418 <<
" .BITSIZE_m_axi_awaddr(BITSIZE_address),\n" 419 <<
" .BITSIZE_m_axi_awlen(BITSIZE_awlen),\n" 420 <<
" .BITSIZE_m_axi_wdata(" << be_data_w <<
"),\n" 421 <<
" .BITSIZE_m_axi_wstrb(" << be_data_w <<
" / 8),\n" 422 <<
" .BITSIZE_m_axi_bid(BITSIZE_bid),\n" 423 <<
" .BITSIZE_m_axi_arid(BITSIZE_arid),\n" 424 <<
" .BITSIZE_m_axi_araddr(BITSIZE_address),\n" 425 <<
" .BITSIZE_m_axi_arlen(BITSIZE_arlen),\n" 426 <<
" .BITSIZE_m_axi_rid(BITSIZE_rid),\n" 427 <<
" .BITSIZE_m_axi_rdata(" << be_data_w <<
")) cache(.addr(addr),\n" 428 <<
" .wdata(" << _ports_in[
i_in3].name <<
"),\n" 429 <<
" .wstrb(wstrb),\n" 430 <<
" .rdata(rdata),\n" 431 <<
" .ready(ready),\n" 432 <<
" .valid(" << _ports_in[
i_start].name <<
" && !(" << _ports_in[
i_in1].name <<
" && " 433 << _ports_in[
i_in2].name <<
" == 0)),\n" 434 <<
" .dirty(dirty),\n" 435 <<
" .flush(state == S_FLUSH),\n" 436 <<
" .m_axi_awready(" << _ports_in[
i_awready].name <<
"),\n" 437 <<
" .m_axi_wready(" << _ports_in[
i_wready].name <<
"),\n" 438 <<
" .m_axi_bid(" << _ports_in[
i_bid].name <<
"),\n" 439 <<
" .m_axi_bresp(" << _ports_in[
i_bresp].name <<
"),\n" 440 <<
" .m_axi_bvalid(" << _ports_in[
i_bvalid].name <<
"),\n" 441 <<
" .m_axi_arready(" << _ports_in[
i_arready].name <<
"),\n" 442 <<
" .m_axi_rid(" << _ports_in[
i_rid].name <<
"),\n" 443 <<
" .m_axi_rdata(" << _ports_in[
i_rdata].name <<
"),\n" 444 <<
" .m_axi_rresp(" << _ports_in[
i_rresp].name <<
"),\n" 445 <<
" .m_axi_rlast(" << _ports_in[
i_rlast].name <<
"),\n" 446 <<
" .m_axi_rvalid(" << _ports_in[
i_rvalid].name <<
"),\n" 447 <<
" .m_axi_awid(" << _ports_out[
o_awid].name <<
"),\n" 448 <<
" .m_axi_awaddr(" << _ports_out[
o_awaddr].name <<
"),\n" 449 <<
" .m_axi_awlen(" << _ports_out[
o_awlen].name <<
"),\n" 450 <<
" .m_axi_awsize(" << _ports_out[
o_awsize].name <<
"),\n" 451 <<
" .m_axi_awburst(" << _ports_out[
o_awburst].name <<
"),\n" 452 <<
" .m_axi_awlock(" << _ports_out[
o_awlock].name <<
"),\n" 453 <<
" .m_axi_awcache(" << _ports_out[
o_awcache].name <<
"),\n" 454 <<
" .m_axi_awprot(" << _ports_out[
o_awprot].name <<
"),\n" 455 <<
" .m_axi_awqos(" << _ports_out[
o_awqos].name <<
"),\n" 456 <<
" .m_axi_awvalid(" << _ports_out[
o_awvalid].name <<
"),\n" 457 <<
" .m_axi_wdata(" << _ports_out[
o_wdata].name <<
"),\n" 458 <<
" .m_axi_wstrb(" << _ports_out[
o_wstrb].name <<
"),\n" 459 <<
" .m_axi_wlast(" << _ports_out[
o_wlast].name <<
"),\n" 460 <<
" .m_axi_wvalid(" << _ports_out[
o_wvalid].name <<
"),\n" 461 <<
" .m_axi_bready(" << _ports_out[
o_bready].name <<
"),\n" 462 <<
" .m_axi_arid(" << _ports_out[
o_arid].name <<
"),\n" 463 <<
" .m_axi_araddr(" << _ports_out[
o_araddr].name <<
"),\n" 464 <<
" .m_axi_arlen(" << _ports_out[
o_arlen].name <<
"),\n" 465 <<
" .m_axi_arsize(" << _ports_out[
o_arsize].name <<
"),\n" 466 <<
" .m_axi_arburst(" << _ports_out[
o_arburst].name <<
"),\n" 467 <<
" .m_axi_arlock(" << _ports_out[
o_arlock].name <<
"),\n" 468 <<
" .m_axi_arcache(" << _ports_out[
o_arcache].name <<
"),\n" 469 <<
" .m_axi_arprot(" << _ports_out[
o_arprot].name <<
"),\n" 470 <<
" .m_axi_arqos(" << _ports_out[
o_arqos].name <<
"),\n" 471 <<
" .m_axi_arvalid(" << _ports_out[
o_arvalid].name <<
"),\n" 472 <<
" .m_axi_rready(" << _ports_out[
o_rready].name <<
"),\n" 473 <<
" .clock(clock),\n" 474 <<
" .reset(reset));\n\n" 475 <<
"`undef _CACHE_CNT\n";
Data structure representing the entire HLS information.
#define STR_CST_interface_parameter_keyword
interface_parameter_keyword
const std::string & get_id() const
Return the identifier associated with the structural_object.
mathematical utility function not provided by standard libraries
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
T ceil_log2(T x)
Return the smallest n such that 2**n >= X.
static void add_NP_functionality(structural_objectRef cir, NP_functionality::NP_functionaly_type dt, std::string functionality_description)
Add a not-parsed functionality.
This class writes different HDL based descriptions (VHDL, Verilog, SystemC) starting from a structura...
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
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
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
This class describes all classes used to represent a structural object.
ReadWrite_m_axiModuleGenerator(const HLS_managerRef &HLSMgr)
#define BURST_TYPE_STR(type)
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Class implementation of the structural_manager.
Data structure definition for high-level synthesis flow.
HLS specialization of generic_device.
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 ...