diff --git a/ci/blackbox.sh b/ci/blackbox.sh index 9c619acca..6b28ab320 100755 --- a/ci/blackbox.sh +++ b/ci/blackbox.sh @@ -156,6 +156,7 @@ make -C $VORTEX_HOME/runtime/stub if [ $DEBUG -ne 0 ] then + # driver initialization if [ $SCOPE -eq 1 ] then echo "running: DEBUG=$DEBUG_LEVEL SCOPE=1 CONFIGS="$CONFIGS" make -C $DRIVER_PATH" @@ -165,6 +166,7 @@ then DEBUG=$DEBUG_LEVEL CONFIGS="$CONFIGS" make -C $DRIVER_PATH fi + # running application if [ $HAS_ARGS -eq 1 ] then echo "running: OPTS=$ARGS make -C $APP_PATH run-$DRIVER > run.log 2>&1" @@ -181,7 +183,7 @@ then mv -f $APP_PATH/trace.vcd . fi else - echo "driver initialization..." + # driver initialization if [ $SCOPE -eq 1 ] then echo "running: SCOPE=1 CONFIGS="$CONFIGS" make -C $DRIVER_PATH" @@ -191,7 +193,7 @@ else CONFIGS="$CONFIGS" make -C $DRIVER_PATH fi - echo "running application..." + # running application if [ $HAS_ARGS -eq 1 ] then echo "running: OPTS=$ARGS make -C $APP_PATH run-$DRIVER" diff --git a/hw/rtl/VX_cluster.sv b/hw/rtl/VX_cluster.sv index 56952c8dc..701e452c2 100644 --- a/hw/rtl/VX_cluster.sv +++ b/hw/rtl/VX_cluster.sv @@ -20,7 +20,7 @@ import VX_gpu_types::*; module VX_cluster #( parameter CLUSTER_ID = 0 ) ( - `SCOPE_IO_VX_cluster + `SCOPE_IO_DECL // Clock input wire clk, @@ -459,6 +459,8 @@ module VX_cluster #( `BUFFER_DCR_WRITE_IF (socket_dcr_write_if, socket_dcr_write_tmp_if, (`NUM_SOCKETS > 1)); + `SCOPE_IO_SWITCH (`NUM_SOCKETS); + // Generate all sockets for (genvar i = 0; i < `NUM_SOCKETS; ++i) begin @@ -467,7 +469,7 @@ module VX_cluster #( VX_socket #( .SOCKET_ID ((CLUSTER_ID * `NUM_SOCKETS) + i) ) socket ( - `SCOPE_BIND_VX_cluster_socket(i) + `SCOPE_IO_BIND (i) .clk (clk), .reset (socket_reset), diff --git a/hw/rtl/VX_mem_unit.sv b/hw/rtl/VX_mem_unit.sv index 946369167..c2c5177b3 100644 --- a/hw/rtl/VX_mem_unit.sv +++ b/hw/rtl/VX_mem_unit.sv @@ -119,13 +119,13 @@ module VX_mem_unit # ( .NUM_REQS (DCACHE_NUM_REQS), .WORD_SIZE (DCACHE_WORD_SIZE), .TAG_WIDTH (DCACHE_NOSM_TAG_WIDTH) - ) dcache_nosm_req_if [`NUM_SOCKETS](); + ) dcache_switch_req_if [`NUM_SOCKETS](); VX_cache_rsp_if #( .NUM_REQS (DCACHE_NUM_REQS), .WORD_SIZE (DCACHE_WORD_SIZE), .TAG_WIDTH (DCACHE_NOSM_TAG_WIDTH) - ) dcache_nosm_rsp_if [`NUM_SOCKETS](); + ) dcache_switch_rsp_if [`NUM_SOCKETS](); `RESET_RELAY (dcache_reset, reset); @@ -159,8 +159,8 @@ module VX_mem_unit # ( .clk (clk), .reset (dcache_reset), - .core_req_if (dcache_nosm_req_if), - .core_rsp_if (dcache_nosm_rsp_if), + .core_req_if (dcache_switch_req_if), + .core_rsp_if (dcache_switch_rsp_if), .mem_req_if (dcache_mem_req_if), .mem_rsp_if (dcache_mem_rsp_if) ); @@ -174,13 +174,13 @@ module VX_mem_unit # ( .NUM_REQS (DCACHE_NUM_REQS), .WORD_SIZE (DCACHE_WORD_SIZE), .TAG_WIDTH (DCACHE_NOSM_TAG_WIDTH) - ) dcache_smem_switch_req_if[2](); + ) smem_switch_out_req_if[2](); VX_cache_rsp_if #( .NUM_REQS (DCACHE_NUM_REQS), .WORD_SIZE (DCACHE_WORD_SIZE), .TAG_WIDTH (DCACHE_NOSM_TAG_WIDTH) - ) dcache_smem_switch_rsp_if[2](); + ) smem_switch_out_rsp_if[2](); `RESET_RELAY (dcache_smem_switch_reset, reset); @@ -198,12 +198,12 @@ module VX_mem_unit # ( .reset (dcache_smem_switch_reset), .req_in_if (dcache_req_if[i]), .rsp_in_if (dcache_rsp_if[i]), - .req_out_if (dcache_smem_switch_req_if), - .rsp_out_if (dcache_smem_switch_rsp_if) + .req_out_if (smem_switch_out_req_if), + .rsp_out_if (smem_switch_out_rsp_if) ); - `ASSIGN_VX_CACHE_REQ_IF (dcache_nosm_req_if[i], dcache_smem_switch_req_if[0]); - `ASSIGN_VX_CACHE_RSP_IF (dcache_smem_switch_rsp_if[0], dcache_nosm_rsp_if[i]); + `ASSIGN_VX_CACHE_REQ_IF (dcache_switch_req_if[i], smem_switch_out_req_if[0]); + `ASSIGN_VX_CACHE_RSP_IF (smem_switch_out_rsp_if[0], dcache_switch_rsp_if[i]); // shared memory address mapping: // [core_idx][warp_idx][word_idx][thread_idx] <= [core_idx][warp_idx][thread_idx][bank_offset..word_idx] @@ -217,14 +217,14 @@ module VX_mem_unit # ( for (genvar j = 0; j < DCACHE_NUM_REQS; ++j) begin if (`NT_BITS != 0) begin - assign smem_req_addr[j][0 +: `NT_BITS] = dcache_smem_switch_req_if[1].addr[j][BANK_ADDR_OFFSET +: `NT_BITS]; + assign smem_req_addr[j][0 +: `NT_BITS] = smem_switch_out_req_if[1].addr[j][BANK_ADDR_OFFSET +: `NT_BITS]; end - assign smem_req_addr[j][`NT_BITS +: WORD_SEL_BITS] = dcache_smem_switch_req_if[1].addr[j][0 +: WORD_SEL_BITS]; + assign smem_req_addr[j][`NT_BITS +: WORD_SEL_BITS] = smem_switch_out_req_if[1].addr[j][0 +: WORD_SEL_BITS]; if (`NW_BITS != 0) begin - assign smem_req_addr[j][(`NT_BITS + WORD_SEL_BITS) +: `NW_BITS] = dcache_smem_switch_req_if[1].addr[j][(BANK_ADDR_OFFSET + `NT_BITS) +: `NW_BITS]; + assign smem_req_addr[j][(`NT_BITS + WORD_SEL_BITS) +: `NW_BITS] = smem_switch_out_req_if[1].addr[j][(BANK_ADDR_OFFSET + `NT_BITS) +: `NW_BITS]; end if (SOCKET_BITS != 0) begin - assign smem_req_addr[j][(`NT_BITS + WORD_SEL_BITS + `NW_BITS) +: SOCKET_BITS] = dcache_smem_switch_req_if[1].addr[j][(BANK_ADDR_OFFSET + `NT_BITS + `NW_BITS) +: SOCKET_BITS]; + assign smem_req_addr[j][(`NT_BITS + WORD_SEL_BITS + `NW_BITS) +: SOCKET_BITS] = smem_switch_out_req_if[1].addr[j][(BANK_ADDR_OFFSET + `NT_BITS + `NW_BITS) +: SOCKET_BITS]; end end @@ -249,27 +249,27 @@ module VX_mem_unit # ( `endif // Core request - .req_valid (dcache_smem_switch_req_if[1].valid), - .req_rw (dcache_smem_switch_req_if[1].rw), - .req_byteen (dcache_smem_switch_req_if[1].byteen), + .req_valid (smem_switch_out_req_if[1].valid), + .req_rw (smem_switch_out_req_if[1].rw), + .req_byteen (smem_switch_out_req_if[1].byteen), .req_addr (smem_req_addr), - .req_data (dcache_smem_switch_req_if[1].data), - .req_tag (dcache_smem_switch_req_if[1].tag), - .req_ready (dcache_smem_switch_req_if[1].ready), + .req_data (smem_switch_out_req_if[1].data), + .req_tag (smem_switch_out_req_if[1].tag), + .req_ready (smem_switch_out_req_if[1].ready), // Core response - .rsp_valid (dcache_smem_switch_rsp_if[1].valid), - .rsp_data (dcache_smem_switch_rsp_if[1].data), - .rsp_tag (dcache_smem_switch_rsp_if[1].tag), - .rsp_ready (dcache_smem_switch_rsp_if[1].ready) + .rsp_valid (smem_switch_out_rsp_if[1].valid), + .rsp_data (smem_switch_out_rsp_if[1].data), + .rsp_tag (smem_switch_out_rsp_if[1].tag), + .rsp_ready (smem_switch_out_rsp_if[1].ready) ); end `else for (genvar i = 0; i < `NUM_SOCKETS; ++i) begin - `ASSIGN_VX_CACHE_REQ_IF (dcache_nosm_req_if[i], dcache_req_if[i]); - `ASSIGN_VX_CACHE_RSP_IF (dcache_rsp_if[i], dcache_nosm_rsp_if[i]); + `ASSIGN_VX_CACHE_REQ_IF (dcache_switch_req_if[i], dcache_req_if[i]); + `ASSIGN_VX_CACHE_RSP_IF (dcache_rsp_if[i], dcache_switch_rsp_if[i]); end `endif diff --git a/hw/rtl/VX_platform.vh b/hw/rtl/VX_platform.vh index c3c717317..715f99c3b 100644 --- a/hw/rtl/VX_platform.vh +++ b/hw/rtl/VX_platform.vh @@ -56,7 +56,8 @@ /* verilator lint_off DECLFILENAME */ \ /* verilator lint_off IMPLICIT */ \ /* verilator lint_off PINMISSING */ \ - /* verilator lint_off IMPORTSTAR */ + /* verilator lint_off IMPORTSTAR */ \ + /* verilator lint_off UNSIGNED */ `define IGNORE_WARNINGS_END /* verilator lint_on UNUSED */ \ /* verilator lint_on PINCONNECTEMPTY */ \ @@ -66,7 +67,8 @@ /* verilator lint_on DECLFILENAME */ \ /* verilator lint_on IMPLICIT */ \ /* verilator lint_off PINMISSING */ \ - /* verilator lint_on IMPORTSTAR */ + /* verilator lint_on IMPORTSTAR */ \ + /* verilator lint_on UNSIGNED */ `define UNUSED_PARAM(x) /* verilator lint_off UNUSED */ \ localparam __``x = x; \ diff --git a/hw/rtl/VX_scope.vh b/hw/rtl/VX_scope.vh index 1a321a7a2..93007cb5d 100644 --- a/hw/rtl/VX_scope.vh +++ b/hw/rtl/VX_scope.vh @@ -3,97 +3,38 @@ `ifdef SCOPE -`include "scope-defs.vh" +`define SCOPE_IO_DECL \ + input wire scope_reset, \ + input wire scope_bus_in, \ + output wire scope_bus_out, -`define SCOPE_ASSIGN(d,s) assign scope_``d = s +`define SCOPE_IO_SWITCH(count) \ + wire scope_bus_in_w [count]; \ + wire scope_bus_out_w [count]; \ + `RESET_RELAY_EX(scope_reset_w, scope_reset, count, 4); \ + VX_scope_switch #( \ + .N (count) \ + ) scope_switch ( \ + .clk (clk), \ + .reset (scope_reset), \ + .req_in (scope_bus_in), \ + .rsp_out (scope_bus_out), \ + .req_out (scope_bus_in_w), \ + .rsp_in (scope_bus_out_w) \ + ); -`define SCOPE_SIZE 256 +`define SCOPE_IO_BIND(i) \ + .scope_reset (scope_reset_w[i]), \ + .scope_bus_in (scope_bus_in_w[i]), \ + .scope_bus_out (scope_bus_out_w[i]), `else -`define SCOPE_IO_VX_icache_stage +`define SCOPE_IO_DECL -`define SCOPE_IO_VX_fetch +`define SCOPE_IO_SWITCH(n) -`define SCOPE_BIND_VX_fetch_icache_stage - -`define SCOPE_BIND_VX_fetch_warp_sched - -`define SCOPE_IO_VX_warp_sched - -`define SCOPE_BIND_VX_core_fetch - -`define SCOPE_IO_VX_core - -`define SCOPE_IO_VX_socket - -`define SCOPE_IO_VX_cluster - -`define SCOPE_BIND_VX_cluster_socket(__i__) - -`define SCOPE_BIND_VX_socket_core(__i__) - -`define SCOPE_IO_Vortex - -`define SCOPE_BIND_Vortex_cluster(__i__) - -`define SCOPE_BIND_afu_vortex - -`define SCOPE_IO_VX_lsu_unit - -`define SCOPE_IO_VX_gpu_unit - -`define SCOPE_IO_VX_execute - -`define SCOPE_BIND_VX_execute_lsu_unit - -`define SCOPE_BIND_VX_execute_gpu_unit - -`define SCOPE_BIND_VX_core_execute - -`define SCOPE_IO_VX_issue - -`define SCOPE_BIND_VX_core_issue - -`define SCOPE_IO_VX_cache_bank - -`define SCOPE_IO_VX_cache - -`define SCOPE_IO_VX_cache_wrap - -`define SCOPE_BIND_VX_cache_wrap_cache - -`define SCOPE_BIND_VX_cache_bank(__i__) - -`define SCOPE_BIND_Vortex_l3cache - -`define SCOPE_BIND_VX_cluster_l2cache - -`define SCOPE_BIND_VX_cluster_rcache - -`define SCOPE_BIND_VX_cluster_ocache - -`define SCOPE_IO_VX_mem_unit - -`define SCOPE_BIND_VX_core_mem_unit - -`define SCOPE_BIND_VX_mem_unit_dcache - -`define SCOPE_BIND_VX_mem_unit_icache - -`define SCOPE_BIND_VX_mem_unit_tcache - -`define SCOPE_BIND_VX_mem_unit_smem - -`define SCOPE_DECL_SIGNALS - -`define SCOPE_DATA_LIST - -`define SCOPE_UPDATE_LIST - -`define SCOPE_TRIGGER - -`define SCOPE_ASSIGN(d,s) +`define SCOPE_IO_BIND(i) `endif diff --git a/hw/rtl/VX_socket.sv b/hw/rtl/VX_socket.sv index 264536c9f..8bac35845 100644 --- a/hw/rtl/VX_socket.sv +++ b/hw/rtl/VX_socket.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_socket #( parameter SOCKET_ID = 0 ) ( - `SCOPE_IO_VX_socket + `SCOPE_IO_DECL // Clock input wire clk, @@ -317,6 +317,8 @@ module VX_socket #( `BUFFER_DCR_WRITE_IF (core_dcr_write_if, dcr_write_if, (`SOCKET_SIZE > 1)); + `SCOPE_IO_SWITCH (`SOCKET_SIZE) + // Generate all cores for (genvar i = 0; i < `SOCKET_SIZE; ++i) begin @@ -325,7 +327,7 @@ module VX_socket #( VX_core #( .CORE_ID ((SOCKET_ID * `SOCKET_SIZE) + i) ) core ( - `SCOPE_BIND_VX_socket_core(i) + `SCOPE_IO_BIND (i) .clk (clk), .reset (core_reset), diff --git a/hw/rtl/Vortex.sv b/hw/rtl/Vortex.sv index d6b1712d0..0196bf25c 100644 --- a/hw/rtl/Vortex.sv +++ b/hw/rtl/Vortex.sv @@ -18,7 +18,7 @@ import VX_gpu_types::*; `IGNORE_WARNINGS_END module Vortex ( - `SCOPE_IO_Vortex + `SCOPE_IO_DECL // Clock input wire clk, @@ -141,6 +141,8 @@ module Vortex ( wire [`NUM_CLUSTERS-1:0] per_cluster_busy; + `SCOPE_IO_SWITCH (`NUM_CLUSTERS+1) + // Generate all clusters for (genvar i = 0; i < `NUM_CLUSTERS; ++i) begin @@ -151,7 +153,7 @@ module Vortex ( VX_cluster #( .CLUSTER_ID (i) ) cluster ( - `SCOPE_BIND_Vortex_cluster(i) + `SCOPE_IO_BIND (i) .clk (clk), .reset (cluster_reset), @@ -312,12 +314,22 @@ module Vortex ( `endif - `SCOPE_ASSIGN (reset, reset); - `SCOPE_ASSIGN (mem_req_fire, mem_req_fire); - `SCOPE_ASSIGN (mem_req_addr, `TO_FULL_ADDR(mem_req_addr)); - `SCOPE_ASSIGN (mem_req_rw, mem_req_rw); - `SCOPE_ASSIGN (mem_rsp_fire, mem_rsp_fire); - `SCOPE_ASSIGN (busy, busy); +`ifdef SCOPE + VX_scope_tap #( + .SCOPE_ID (1), + .TRIGGERW (2), + .PROBEW (`VX_MEM_ADDR_WIDTH+1+1) + ) scope_tap ( + .clk(clk), + .reset(scope_reset_w[`NUM_CLUSTERS]), + .start(1'b0), + .stop(1'b0), + .triggers({mem_req_fire, mem_rsp_fire}), + .probes({mem_req_addr, mem_req_rw, busy}), + .bus_in(scope_bus_in_w[`NUM_CLUSTERS]), + .bus_out(scope_bus_out_w[`NUM_CLUSTERS]) + ); +`endif `ifdef DBG_TRACE_CORE_MEM always @(posedge clk) begin diff --git a/hw/rtl/afu/opae/vortex_afu.sv b/hw/rtl/afu/opae/vortex_afu.sv index 84f069f22..ec5219966 100644 --- a/hw/rtl/afu/opae/vortex_afu.sv +++ b/hw/rtl/afu/opae/vortex_afu.sv @@ -17,1032 +17,1089 @@ import VX_gpu_types::*; /* verilator lint_on IMPORTSTAR */ module vortex_afu #( - parameter NUM_LOCAL_MEM_BANKS = 2 + parameter NUM_LOCAL_MEM_BANKS = 2 ) ( - // global signals - input wire clk, - input wire reset, + // global signals + input wire clk, + input wire reset, - // IF signals between CCI and AFU - input t_if_ccip_Rx cp2af_sRxPort, - output t_if_ccip_Tx af2cp_sTxPort, + // IF signals between CCI and AFU + input t_if_ccip_Rx cp2af_sRxPort, + output t_if_ccip_Tx af2cp_sTxPort, - // Avalon signals for local memory access - output t_local_mem_data avs_writedata [NUM_LOCAL_MEM_BANKS], - input t_local_mem_data avs_readdata [NUM_LOCAL_MEM_BANKS], - output t_local_mem_addr avs_address [NUM_LOCAL_MEM_BANKS], - input wire avs_waitrequest [NUM_LOCAL_MEM_BANKS], - output wire avs_write [NUM_LOCAL_MEM_BANKS], - output wire avs_read [NUM_LOCAL_MEM_BANKS], - output t_local_mem_byte_mask avs_byteenable [NUM_LOCAL_MEM_BANKS], - output t_local_mem_burst_cnt avs_burstcount [NUM_LOCAL_MEM_BANKS], - input wire avs_readdatavalid [NUM_LOCAL_MEM_BANKS] + // Avalon signals for local memory access + output t_local_mem_data avs_writedata [NUM_LOCAL_MEM_BANKS], + input t_local_mem_data avs_readdata [NUM_LOCAL_MEM_BANKS], + output t_local_mem_addr avs_address [NUM_LOCAL_MEM_BANKS], + input wire avs_waitrequest [NUM_LOCAL_MEM_BANKS], + output wire avs_write [NUM_LOCAL_MEM_BANKS], + output wire avs_read [NUM_LOCAL_MEM_BANKS], + output t_local_mem_byte_mask avs_byteenable [NUM_LOCAL_MEM_BANKS], + output t_local_mem_burst_cnt avs_burstcount [NUM_LOCAL_MEM_BANKS], + input wire avs_readdatavalid [NUM_LOCAL_MEM_BANKS] ); -localparam LMEM_DATA_WIDTH = $bits(t_local_mem_data); -localparam LMEM_ADDR_WIDTH = $bits(t_local_mem_addr); -localparam LMEM_BURST_CTRW = $bits(t_local_mem_burst_cnt); + localparam LMEM_DATA_WIDTH = $bits(t_local_mem_data); + localparam LMEM_ADDR_WIDTH = $bits(t_local_mem_addr); + localparam LMEM_BURST_CTRW = $bits(t_local_mem_burst_cnt); -localparam CCI_DATA_WIDTH = $bits(t_ccip_clData); -localparam CCI_DATA_SIZE = CCI_DATA_WIDTH / 8; -localparam CCI_ADDR_WIDTH = 32 - $clog2(CCI_DATA_SIZE); + localparam CCI_DATA_WIDTH = $bits(t_ccip_clData); + localparam CCI_DATA_SIZE = CCI_DATA_WIDTH / 8; + localparam CCI_ADDR_WIDTH = 32 - $clog2(CCI_DATA_SIZE); + localparam AVS_RD_QUEUE_SIZE = 32; + localparam _VX_MEM_TAG_WIDTH = `VX_MEM_TAG_WIDTH; + localparam _AVS_REQ_TAGW_VX = _VX_MEM_TAG_WIDTH + $clog2(LMEM_DATA_WIDTH) - $clog2(`VX_MEM_DATA_WIDTH); + localparam _AVS_REQ_TAGW_VX2 = `MAX(_VX_MEM_TAG_WIDTH, _AVS_REQ_TAGW_VX); + localparam _AVS_REQ_TAGW_CCI = CCI_ADDR_WIDTH + $clog2(LMEM_DATA_WIDTH) - $clog2(CCI_DATA_WIDTH); + localparam _AVS_REQ_TAGW_CCI2 = `MAX(CCI_ADDR_WIDTH, _AVS_REQ_TAGW_CCI); + localparam AVS_REQ_TAGW = `MAX(_AVS_REQ_TAGW_VX2, _AVS_REQ_TAGW_CCI2); -localparam AVS_RD_QUEUE_SIZE = 32; -localparam _VX_MEM_TAG_WIDTH = `VX_MEM_TAG_WIDTH; -localparam _AVS_REQ_TAGW_VX = _VX_MEM_TAG_WIDTH + $clog2(LMEM_DATA_WIDTH) - $clog2(`VX_MEM_DATA_WIDTH); -localparam _AVS_REQ_TAGW_VX2 = `MAX(_VX_MEM_TAG_WIDTH, _AVS_REQ_TAGW_VX); -localparam _AVS_REQ_TAGW_CCI = CCI_ADDR_WIDTH + $clog2(LMEM_DATA_WIDTH) - $clog2(CCI_DATA_WIDTH); -localparam _AVS_REQ_TAGW_CCI2 = `MAX(CCI_ADDR_WIDTH, _AVS_REQ_TAGW_CCI); -localparam AVS_REQ_TAGW = `MAX(_AVS_REQ_TAGW_VX2, _AVS_REQ_TAGW_CCI2); + localparam CCI_RD_WINDOW_SIZE = 8; + localparam CCI_RW_PENDING_SIZE= 256; -localparam CCI_RD_WINDOW_SIZE = 8; -localparam CCI_RW_PENDING_SIZE= 256; + localparam AFU_ID_L = 16'h0002; // AFU ID Lower + localparam AFU_ID_H = 16'h0004; // AFU ID Higher -localparam AFU_ID_L = 16'h0002; // AFU ID Lower -localparam AFU_ID_H = 16'h0004; // AFU ID Higher + localparam CMD_MEM_READ = `AFU_IMAGE_CMD_MEM_READ; + localparam CMD_MEM_WRITE = `AFU_IMAGE_CMD_MEM_WRITE; + localparam CMD_DCR_WRITE = `AFU_IMAGE_CMD_DCR_WRITE; + localparam CMD_RUN = `AFU_IMAGE_CMD_RUN; + localparam CMD_TYPE_WIDTH = $clog2(`AFU_IMAGE_CMD_MAX_VALUE+1); -localparam CMD_MEM_READ = `AFU_IMAGE_CMD_MEM_READ; -localparam CMD_MEM_WRITE = `AFU_IMAGE_CMD_MEM_WRITE; -localparam CMD_DCR_WRITE = `AFU_IMAGE_CMD_DCR_WRITE; -localparam CMD_RUN = `AFU_IMAGE_CMD_RUN; -localparam CMD_TYPE_WIDTH = $clog2(`AFU_IMAGE_CMD_MAX_VALUE+1); + localparam MMIO_CMD_TYPE = `AFU_IMAGE_MMIO_CMD_TYPE; + localparam MMIO_CMD_ARG0 = `AFU_IMAGE_MMIO_CMD_ARG0; + localparam MMIO_CMD_ARG1 = `AFU_IMAGE_MMIO_CMD_ARG1; + localparam MMIO_CMD_ARG2 = `AFU_IMAGE_MMIO_CMD_ARG2; + localparam MMIO_STATUS = `AFU_IMAGE_MMIO_STATUS; -localparam MMIO_CMD_TYPE = `AFU_IMAGE_MMIO_CMD_TYPE; -localparam MMIO_CMD_ARG0 = `AFU_IMAGE_MMIO_CMD_ARG0; -localparam MMIO_CMD_ARG1 = `AFU_IMAGE_MMIO_CMD_ARG1; -localparam MMIO_CMD_ARG2 = `AFU_IMAGE_MMIO_CMD_ARG2; -localparam MMIO_STATUS = `AFU_IMAGE_MMIO_STATUS; + localparam COUT_TID_WIDTH = $clog2(`VX_MEM_BYTEEN_WIDTH); + localparam COUT_QUEUE_DATAW = COUT_TID_WIDTH + 8; + localparam COUT_QUEUE_SIZE = 64; -localparam COUT_TID_WIDTH = $clog2(`VX_MEM_BYTEEN_WIDTH); -localparam COUT_QUEUE_DATAW = COUT_TID_WIDTH + 8; -localparam COUT_QUEUE_SIZE = 64; + localparam MMIO_DEV_CAPS = `AFU_IMAGE_MMIO_DEV_CAPS; + localparam MMIO_ISA_CAPS = `AFU_IMAGE_MMIO_ISA_CAPS; -localparam MMIO_SCOPE_READ = `AFU_IMAGE_MMIO_SCOPE_READ; -localparam MMIO_SCOPE_WRITE = `AFU_IMAGE_MMIO_SCOPE_WRITE; + localparam CCI_RD_QUEUE_SIZE = 2 * CCI_RD_WINDOW_SIZE; + localparam CCI_RD_QUEUE_TAGW = $clog2(CCI_RD_WINDOW_SIZE); + localparam CCI_RD_QUEUE_DATAW = CCI_DATA_WIDTH + CCI_ADDR_WIDTH; -localparam MMIO_DEV_CAPS = `AFU_IMAGE_MMIO_DEV_CAPS; -localparam MMIO_ISA_CAPS = `AFU_IMAGE_MMIO_ISA_CAPS; + localparam STATE_IDLE = 0; + localparam STATE_MEM_WRITE = 1; + localparam STATE_MEM_READ = 2; + localparam STATE_RUN = 3; + localparam STATE_DCR_WRITE = 4; + localparam STATE_WIDTH = $clog2(STATE_DCR_WRITE+1); -localparam CCI_RD_QUEUE_SIZE = 2 * CCI_RD_WINDOW_SIZE; -localparam CCI_RD_QUEUE_TAGW = $clog2(CCI_RD_WINDOW_SIZE); -localparam CCI_RD_QUEUE_DATAW = CCI_DATA_WIDTH + CCI_ADDR_WIDTH; + wire [127:0] afu_id = `AFU_ACCEL_UUID; -localparam STATE_IDLE = 0; -localparam STATE_MEM_WRITE = 1; -localparam STATE_MEM_READ = 2; -localparam STATE_RUN = 3; -localparam STATE_DCR_WRITE = 4; -localparam STATE_WIDTH = $clog2(STATE_DCR_WRITE+1); + wire [63:0] dev_caps = {16'(`NUM_THREADS), + 16'(`NUM_WARPS), + 16'(`NUM_CORES * `NUM_CLUSTERS), + 16'(`IMPLEMENTATION_ID)}; + + wire [63:0] isa_caps = {32'(`MISA_EXT), 2'($clog2(`XLEN)-4), 30'(`MISA_STD)}; + + reg [STATE_WIDTH-1:0] state; + + // Vortex ports /////////////////////////////////////////////////////////////// + + wire vx_mem_req_valid; + wire vx_mem_req_rw; + wire [`VX_MEM_BYTEEN_WIDTH-1:0] vx_mem_req_byteen; + wire [`VX_MEM_ADDR_WIDTH-1:0] vx_mem_req_addr; + wire [`VX_MEM_DATA_WIDTH-1:0] vx_mem_req_data; + wire [`VX_MEM_TAG_WIDTH-1:0] vx_mem_req_tag; + wire vx_mem_req_ready; + + wire vx_mem_rsp_valid; + wire [`VX_MEM_DATA_WIDTH-1:0] vx_mem_rsp_data; + wire [`VX_MEM_TAG_WIDTH-1:0] vx_mem_rsp_tag; + wire vx_mem_rsp_ready; + + // CMD variables ////////////////////////////////////////////////////////////// + + reg [2:0][63:0] cmd_args; + + t_ccip_clAddr cmd_io_addr; + assign cmd_io_addr = t_ccip_clAddr'(cmd_args[0]); + + wire [CCI_ADDR_WIDTH-1:0] cmd_mem_addr = CCI_ADDR_WIDTH'(cmd_args[1]); + wire [CCI_ADDR_WIDTH-1:0] cmd_data_size = CCI_ADDR_WIDTH'(cmd_args[2]); + + wire [`VX_DCR_ADDR_WIDTH-1:0] cmd_dcr_addr = `VX_DCR_ADDR_WIDTH'(cmd_args[0]); + wire [`VX_DCR_DATA_WIDTH-1:0] cmd_dcr_data = `VX_DCR_DATA_WIDTH'(cmd_args[1]); + + // MMIO controller //////////////////////////////////////////////////////////// + + `IGNORE_UNUSED_BEGIN + t_ccip_c0_ReqMmioHdr mmio_hdr; + `IGNORE_UNUSED_END + assign mmio_hdr = t_ccip_c0_ReqMmioHdr'(cp2af_sRxPort.c0.hdr); + + `STATIC_ASSERT(($bits(t_ccip_c0_ReqMmioHdr)-$bits(mmio_hdr.address)) == 12, ("Oops!")) + + t_if_ccip_c2_Tx mmio_tx; + assign af2cp_sTxPort.c2 = mmio_tx; `ifdef SCOPE -`SCOPE_DECL_SIGNALS + + localparam MMIO_SCOPE_READ = `AFU_IMAGE_MMIO_SCOPE_READ; + localparam MMIO_SCOPE_WRITE = `AFU_IMAGE_MMIO_SCOPE_WRITE; + + reg [63:0] cmd_scope_rdata; + reg [63:0] cmd_scope_wdata; + + reg cmd_scope_reading; + reg cmd_scope_writing; + + reg scope_bus_in; + wire scope_bus_out; + + reg [5:0] scope_bus_ctr; + + wire scope_reset = reset; + + always @(posedge clk) begin + if (reset) begin + cmd_scope_reading <= 0; + cmd_scope_writing <= 0; + scope_bus_in <= 0; + end else begin + if (scope_bus_out) begin + cmd_scope_reading <= 1; + scope_bus_ctr <= 63; + end + scope_bus_in <= 0; + if (cp2af_sRxPort.c0.mmioWrValid + && (MMIO_SCOPE_WRITE == mmio_hdr.address)) begin + cmd_scope_wdata <= 64'(cp2af_sRxPort.c0.data); + cmd_scope_writing <= 1; + scope_bus_ctr <= 63; + scope_bus_in <= 1; + end + end + if (cmd_scope_writing) begin + scope_bus_in <= 1'(cmd_scope_wdata >> scope_bus_ctr); + scope_bus_ctr <= scope_bus_ctr - 1; + if (scope_bus_ctr == 0) begin + cmd_scope_writing <= 0; + end + end + if (cmd_scope_reading) begin + cmd_scope_rdata <= {cmd_scope_rdata[62:0], scope_bus_out}; + scope_bus_ctr <= scope_bus_ctr - 1; + if (scope_bus_ctr == 0) begin + cmd_scope_reading <= 0; + end + end + end + `endif -wire [127:0] afu_id = `AFU_ACCEL_UUID; - -wire [63:0] dev_caps = {16'(`NUM_THREADS), 16'(`NUM_WARPS), 16'(`NUM_CORES * `NUM_CLUSTERS), 16'(`IMPLEMENTATION_ID)}; - -wire [63:0] isa_caps = {32'(`MISA_EXT), 2'($clog2(`XLEN)-4), 30'(`MISA_STD)}; - -reg [STATE_WIDTH-1:0] state; - -// Vortex ports /////////////////////////////////////////////////////////////// - -wire vx_mem_req_valid; -wire vx_mem_req_rw; -wire [`VX_MEM_BYTEEN_WIDTH-1:0] vx_mem_req_byteen; -wire [`VX_MEM_ADDR_WIDTH-1:0] vx_mem_req_addr; -wire [`VX_MEM_DATA_WIDTH-1:0] vx_mem_req_data; -wire [`VX_MEM_TAG_WIDTH-1:0] vx_mem_req_tag; -wire vx_mem_req_ready; - -wire vx_mem_rsp_valid; -wire [`VX_MEM_DATA_WIDTH-1:0] vx_mem_rsp_data; -wire [`VX_MEM_TAG_WIDTH-1:0] vx_mem_rsp_tag; -wire vx_mem_rsp_ready; - -// CMD variables ////////////////////////////////////////////////////////////// - -reg [2:0][63:0] cmd_args; - -t_ccip_clAddr cmd_io_addr; -assign cmd_io_addr = t_ccip_clAddr'(cmd_args[0]); - -wire [CCI_ADDR_WIDTH-1:0] cmd_mem_addr = CCI_ADDR_WIDTH'(cmd_args[1]); -wire [CCI_ADDR_WIDTH-1:0] cmd_data_size = CCI_ADDR_WIDTH'(cmd_args[2]); - -wire [`VX_DCR_ADDR_WIDTH-1:0] cmd_dcr_addr = `VX_DCR_ADDR_WIDTH'(cmd_args[0]); -wire [`VX_DCR_DATA_WIDTH-1:0] cmd_dcr_data = `VX_DCR_DATA_WIDTH'(cmd_args[1]); - -`ifdef SCOPE -wire [63:0] cmd_scope_rdata; -wire [63:0] cmd_scope_wdata; -wire cmd_scope_read; -wire cmd_scope_write; -`endif - -// MMIO controller //////////////////////////////////////////////////////////// - -`IGNORE_UNUSED_BEGIN -t_ccip_c0_ReqMmioHdr mmio_hdr; -`IGNORE_UNUSED_END -assign mmio_hdr = t_ccip_c0_ReqMmioHdr'(cp2af_sRxPort.c0.hdr); - -`STATIC_ASSERT(($bits(t_ccip_c0_ReqMmioHdr)-$bits(mmio_hdr.address)) == 12, ("Oops!")) - -t_if_ccip_c2_Tx mmio_tx; -assign af2cp_sTxPort.c2 = mmio_tx; - -`ifdef SCOPE -assign cmd_scope_wdata = 64'(cp2af_sRxPort.c0.data); -assign cmd_scope_read = cp2af_sRxPort.c0.mmioRdValid && (MMIO_SCOPE_READ == mmio_hdr.address); -assign cmd_scope_write = cp2af_sRxPort.c0.mmioWrValid && (MMIO_SCOPE_WRITE == mmio_hdr.address); -`endif - -wire [COUT_QUEUE_DATAW-1:0] cout_q_dout; -wire cout_q_full, cout_q_empty; + wire [COUT_QUEUE_DATAW-1:0] cout_q_dout; + wire cout_q_full, cout_q_empty; `ifdef SIMULATION `ifndef VERILATOR -// disable assertions until full reset -reg [$clog2(`RESET_DELAY+1)-1:0] assert_delay_ctr; -initial begin - $assertoff; -end -always @(posedge clk) begin - if (reset) begin - assert_delay_ctr <= '0; - end else begin - assert_delay_ctr <= assert_delay_ctr + $bits(assert_delay_ctr)'(1); - if (assert_delay_ctr == (`RESET_DELAY-1)) begin - $asserton; // enable assertions + // disable assertions until full reset + reg [$clog2(`RESET_DELAY+1)-1:0] assert_delay_ctr; + initial begin + $assertoff; end - end -end -`endif -`endif - -always @(posedge clk) begin - if (reset) begin - mmio_tx.mmioRdValid <= 0; - mmio_tx.hdr <= '0; - end else begin - mmio_tx.mmioRdValid <= cp2af_sRxPort.c0.mmioRdValid; - mmio_tx.hdr.tid <= mmio_hdr.tid; - end - - // serve MMIO write request - if (cp2af_sRxPort.c0.mmioWrValid) begin - case (mmio_hdr.address) - MMIO_CMD_ARG0: begin - cmd_args[0] <= 64'(cp2af_sRxPort.c0.data); - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_CMD_ARG0: data=0x%0h\n", $time, 64'(cp2af_sRxPort.c0.data))); - `endif - end - MMIO_CMD_ARG1: begin - cmd_args[1] <= 64'(cp2af_sRxPort.c0.data); - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_CMD_ARG1: data=0x%0h\n", $time, 64'(cp2af_sRxPort.c0.data))); - `endif - end - MMIO_CMD_ARG2: begin - cmd_args[2] <= 64'(cp2af_sRxPort.c0.data); - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_CMD_ARG2: data=%0d\n", $time, 64'(cp2af_sRxPort.c0.data))); - `endif - end - MMIO_CMD_TYPE: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_CMD_TYPE: data=%0d\n", $time, 64'(cp2af_sRxPort.c0.data))); - `endif - end - `ifdef SCOPE - MMIO_SCOPE_WRITE: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_SCOPE_WRITE: data=0x%0h\n", $time, 64'(cp2af_sRxPort.c0.data))); - `endif - end - `endif - default: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: Unknown MMIO Wr: addr=0x%0h, data=0x%0h\n", $time, mmio_hdr.address, 64'(cp2af_sRxPort.c0.data))); - `endif - end - endcase - end - - // serve MMIO read requests - if (cp2af_sRxPort.c0.mmioRdValid) begin - case (mmio_hdr.address) - // AFU header - 16'h0000: mmio_tx.data <= { - 4'b0001, // Feature type = AFU - 8'b0, // reserved - 4'b0, // afu minor revision = 0 - 7'b0, // reserved - 1'b1, // end of DFH list = 1 - 24'b0, // next DFH offset = 0 - 4'b0, // afu major revision = 0 - 12'b0 // feature ID = 0 - }; - AFU_ID_L: mmio_tx.data <= afu_id[63:0]; // afu id low - AFU_ID_H: mmio_tx.data <= afu_id[127:64]; // afu id hi - 16'h0006: mmio_tx.data <= 64'h0; // next AFU - 16'h0008: mmio_tx.data <= 64'h0; // reserved - MMIO_STATUS: begin - mmio_tx.data <= 64'({cout_q_dout, !cout_q_empty, 8'(state)}); - `ifdef DBG_TRACE_AFU - if (state != STATE_WIDTH'(mmio_tx.data)) begin - `TRACE(2, ("%d: MMIO_STATUS: addr=0x%0h, state=%0d\n", $time, mmio_hdr.address, state)); - end - `endif - end - `ifdef SCOPE - MMIO_SCOPE_READ: begin - mmio_tx.data <= cmd_scope_rdata; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_SCOPE_READ: data=0x%0h\n", $time, cmd_scope_rdata)); - `endif - end - `endif - MMIO_DEV_CAPS: begin - mmio_tx.data <= dev_caps; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: MMIO_DEV_CAPS: data=0x%0h\n", $time, dev_caps)); - `endif - end - MMIO_ISA_CAPS: begin - mmio_tx.data <= isa_caps; - `ifdef DBG_TRACE_AFU - if (state != STATE_WIDTH'(mmio_tx.data)) begin - `TRACE(2, ("%d: MMIO_ISA_CAPS: data=%0d\n", $time, isa_caps)); - end - `endif - end - default: begin - mmio_tx.data <= 64'h0; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: Unknown MMIO Rd: addr=0x%0h\n", $time, mmio_hdr.address)); - `endif - end - endcase - end -end - -// COMMAND FSM //////////////////////////////////////////////////////////////// - -wire cmd_mem_rd_done; -reg cmd_mem_wr_done; - -reg vx_busy_wait; -reg vx_running; -wire vx_busy; - -reg [$clog2(`RESET_DELAY+1)-1:0] vx_reset_ctr; -always @(posedge clk) begin - if (state == STATE_RUN) begin - vx_reset_ctr <= vx_reset_ctr + $bits(vx_reset_ctr)'(1); - end else begin - vx_reset_ctr <= '0; - end -end - -wire is_mmio_wr_cmd = cp2af_sRxPort.c0.mmioWrValid && (MMIO_CMD_TYPE == mmio_hdr.address); -wire [CMD_TYPE_WIDTH-1:0] cmd_type = is_mmio_wr_cmd ? CMD_TYPE_WIDTH'(cp2af_sRxPort.c0.data) : CMD_TYPE_WIDTH'(0); - -always @(posedge clk) begin - if (reset) begin - state <= STATE_IDLE; - vx_busy_wait <= 0; - vx_running <= 0; - end else begin - case (state) - STATE_IDLE: begin - case (cmd_type) - CMD_MEM_READ: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE MEM_READ: ia=0x%0h addr=0x%0h size=%0d\n", $time, cmd_io_addr, cmd_mem_addr, cmd_data_size)); - `endif - state <= STATE_MEM_READ; - end - CMD_MEM_WRITE: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE MEM_WRITE: ia=0x%0h addr=0x%0h size=%0d\n", $time, cmd_io_addr, cmd_mem_addr, cmd_data_size)); - `endif - state <= STATE_MEM_WRITE; - end - CMD_DCR_WRITE: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE DCR_WRITE: addr=0x%0h data=%0d\n", $time, cmd_dcr_addr, cmd_dcr_data)); - `endif - state <= STATE_DCR_WRITE; - end - CMD_RUN: begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE RUN\n", $time)); - `endif - state <= STATE_RUN; - end - default: begin - state <= state; - end - endcase - end - - STATE_MEM_READ: begin - if (cmd_mem_rd_done) begin - state <= STATE_IDLE; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE IDLE\n", $time)); - `endif - end - end - - STATE_MEM_WRITE: begin - if (cmd_mem_wr_done) begin - state <= STATE_IDLE; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE IDLE\n", $time)); - `endif - end - end - - STATE_DCR_WRITE: begin - state <= STATE_IDLE; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE IDLE\n", $time)); - `endif - end - - STATE_RUN: begin - if (vx_running) begin - if (vx_busy_wait) begin - // wait until processor goes busy be checking for completion - if (vx_busy) begin - vx_busy_wait <= 0; + always @(posedge clk) begin + if (reset) begin + assert_delay_ctr <= '0; + end else begin + assert_delay_ctr <= assert_delay_ctr + $bits(assert_delay_ctr)'(1); + if (assert_delay_ctr == (`RESET_DELAY-1)) begin + $asserton; // enable assertions end - end else begin - if (~vx_busy) begin - vx_running <= 0; - state <= STATE_IDLE; - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: STATE IDLE\n", $time)); + end + end +`endif +`endif + + always @(posedge clk) begin + if (reset) begin + mmio_tx.mmioRdValid <= 0; + mmio_tx.hdr <= '0; + end else begin + mmio_tx.mmioRdValid <= cp2af_sRxPort.c0.mmioRdValid; + mmio_tx.hdr.tid <= mmio_hdr.tid; + end + // serve MMIO write request + if (cp2af_sRxPort.c0.mmioWrValid) begin + case (mmio_hdr.address) + MMIO_CMD_ARG0: begin + cmd_args[0] <= 64'(cp2af_sRxPort.c0.data); + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_CMD_ARG0: data=0x%0h\n", $time, 64'(cp2af_sRxPort.c0.data))); `endif end - end + MMIO_CMD_ARG1: begin + cmd_args[1] <= 64'(cp2af_sRxPort.c0.data); + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_CMD_ARG1: data=0x%0h\n", $time, 64'(cp2af_sRxPort.c0.data))); + `endif + end + MMIO_CMD_ARG2: begin + cmd_args[2] <= 64'(cp2af_sRxPort.c0.data); + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_CMD_ARG2: data=%0d\n", $time, 64'(cp2af_sRxPort.c0.data))); + `endif + end + MMIO_CMD_TYPE: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_CMD_TYPE: data=%0d\n", $time, 64'(cp2af_sRxPort.c0.data))); + `endif + end + `ifdef SCOPE + MMIO_SCOPE_WRITE: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_SCOPE_WRITE: data=0x%0h\n", $time, cmd_scope_wdata)); + `endif + end + `endif + default: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: Unknown MMIO Wr: addr=0x%0h, data=0x%0h\n", $time, mmio_hdr.address, 64'(cp2af_sRxPort.c0.data))); + `endif + end + endcase + end + + // serve MMIO read requests + if (cp2af_sRxPort.c0.mmioRdValid) begin + case (mmio_hdr.address) + // AFU header + 16'h0000: mmio_tx.data <= { + 4'b0001, // Feature type = AFU + 8'b0, // reserved + 4'b0, // afu minor revision = 0 + 7'b0, // reserved + 1'b1, // end of DFH list = 1 + 24'b0, // next DFH offset = 0 + 4'b0, // afu major revision = 0 + 12'b0 // feature ID = 0 + }; + AFU_ID_L: mmio_tx.data <= afu_id[63:0]; // afu id low + AFU_ID_H: mmio_tx.data <= afu_id[127:64]; // afu id hi + 16'h0006: mmio_tx.data <= 64'h0; // next AFU + 16'h0008: mmio_tx.data <= 64'h0; // reserved + MMIO_STATUS: begin + mmio_tx.data <= 64'({cout_q_dout, !cout_q_empty, 8'(state)}); + `ifdef DBG_TRACE_AFU + if (state != STATE_WIDTH'(mmio_tx.data)) begin + `TRACE(2, ("%d: MMIO_STATUS: addr=0x%0h, state=%0d\n", $time, mmio_hdr.address, state)); + end + `endif + end + `ifdef SCOPE + MMIO_SCOPE_READ: begin + mmio_tx.data <= cmd_scope_rdata; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_SCOPE_READ: data=0x%0h\n", $time, cmd_scope_rdata)); + `endif + end + `endif + MMIO_DEV_CAPS: begin + mmio_tx.data <= dev_caps; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: MMIO_DEV_CAPS: data=0x%0h\n", $time, dev_caps)); + `endif + end + MMIO_ISA_CAPS: begin + mmio_tx.data <= isa_caps; + `ifdef DBG_TRACE_AFU + if (state != STATE_WIDTH'(mmio_tx.data)) begin + `TRACE(2, ("%d: MMIO_ISA_CAPS: data=%0d\n", $time, isa_caps)); + end + `endif + end + default: begin + mmio_tx.data <= 64'h0; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: Unknown MMIO Rd: addr=0x%0h\n", $time, mmio_hdr.address)); + `endif + end + endcase + end + end + + // COMMAND FSM //////////////////////////////////////////////////////////////// + + wire cmd_mem_rd_done; + reg cmd_mem_wr_done; + + reg vx_busy_wait; + reg vx_running; + wire vx_busy; + + reg [$clog2(`RESET_DELAY+1)-1:0] vx_reset_ctr; + always @(posedge clk) begin + if (state == STATE_RUN) begin + vx_reset_ctr <= vx_reset_ctr + $bits(vx_reset_ctr)'(1); end else begin - if (vx_reset_ctr == (`RESET_DELAY-1)) begin - vx_running <= 1; - vx_busy_wait <= 1; - end - end - end - - default:; - - endcase - end -end - -// AVS Controller ///////////////////////////////////////////////////////////// - -wire cci_mem_rd_req_valid; -wire cci_mem_wr_req_valid; -wire [CCI_RD_QUEUE_DATAW-1:0] cci_rdq_dout; - -wire cci_mem_req_valid; -wire cci_mem_req_rw; -wire [CCI_ADDR_WIDTH-1:0] cci_mem_req_addr; -wire [CCI_DATA_WIDTH-1:0] cci_mem_req_data; -wire [CCI_ADDR_WIDTH-1:0] cci_mem_req_tag; -wire cci_mem_req_ready; - -wire cci_mem_rsp_valid; -wire [CCI_DATA_WIDTH-1:0] cci_mem_rsp_data; -wire [CCI_ADDR_WIDTH-1:0] cci_mem_rsp_tag; -wire cci_mem_rsp_ready; - -//-- - -VX_mem_req_if #( - .DATA_WIDTH ($bits(t_local_mem_data)), - .ADDR_WIDTH ($bits(t_local_mem_addr)), - .TAG_WIDTH (AVS_REQ_TAGW) -) cci_vx_mem_req_if[1:0](); - -VX_mem_rsp_if #( - .DATA_WIDTH ($bits(t_local_mem_data)), - .TAG_WIDTH (AVS_REQ_TAGW) -) cci_vx_mem_rsp_if[1:0](); - -VX_mem_adapter #( - .SRC_DATA_WIDTH (CCI_DATA_WIDTH), - .DST_DATA_WIDTH (LMEM_DATA_WIDTH), - .SRC_ADDR_WIDTH (CCI_ADDR_WIDTH), - .DST_ADDR_WIDTH (LMEM_ADDR_WIDTH), - .SRC_TAG_WIDTH (CCI_ADDR_WIDTH), - .DST_TAG_WIDTH (AVS_REQ_TAGW), - .BUFFERED_REQ (0), - .BUFFERED_RSP (0) -) cci_mem_adapter ( - .clk (clk), - .reset (reset), - - .mem_req_valid_in (cci_mem_req_valid), - .mem_req_addr_in (cci_mem_req_addr), - .mem_req_rw_in (cci_mem_req_rw), - .mem_req_byteen_in ({CCI_DATA_SIZE{1'b1}}), - .mem_req_data_in (cci_mem_req_data), - .mem_req_tag_in (cci_mem_req_tag), - .mem_req_ready_in (cci_mem_req_ready), - - .mem_rsp_valid_in (cci_mem_rsp_valid), - .mem_rsp_data_in (cci_mem_rsp_data), - .mem_rsp_tag_in (cci_mem_rsp_tag), - .mem_rsp_ready_in (cci_mem_rsp_ready), - - .mem_req_valid_out (cci_vx_mem_req_if[1].valid), - .mem_req_addr_out (cci_vx_mem_req_if[1].addr), - .mem_req_rw_out (cci_vx_mem_req_if[1].rw), - .mem_req_byteen_out (cci_vx_mem_req_if[1].byteen), - .mem_req_data_out (cci_vx_mem_req_if[1].data), - .mem_req_tag_out (cci_vx_mem_req_if[1].tag), - .mem_req_ready_out (cci_vx_mem_req_if[1].ready), - - .mem_rsp_valid_out (cci_vx_mem_rsp_if[1].valid), - .mem_rsp_data_out (cci_vx_mem_rsp_if[1].data), - .mem_rsp_tag_out (cci_vx_mem_rsp_if[1].tag), - .mem_rsp_ready_out (cci_vx_mem_rsp_if[1].ready) -); - -//-- - -wire vx_mem_is_cout; -wire vx_mem_req_valid_qual; -wire vx_mem_req_ready_qual; - -assign vx_mem_req_valid_qual = vx_mem_req_valid && ~vx_mem_is_cout; - -VX_mem_adapter #( - .SRC_DATA_WIDTH (`VX_MEM_DATA_WIDTH), - .DST_DATA_WIDTH (LMEM_DATA_WIDTH), - .SRC_ADDR_WIDTH (`VX_MEM_ADDR_WIDTH), - .DST_ADDR_WIDTH (LMEM_ADDR_WIDTH), - .SRC_TAG_WIDTH (`VX_MEM_TAG_WIDTH), - .DST_TAG_WIDTH (AVS_REQ_TAGW), - .BUFFERED_REQ (0), - .BUFFERED_RSP (2) -) vx_mem_adapter ( - .clk (clk), - .reset (reset), - - .mem_req_valid_in (vx_mem_req_valid_qual), - .mem_req_addr_in (vx_mem_req_addr), - .mem_req_rw_in (vx_mem_req_rw), - .mem_req_byteen_in (vx_mem_req_byteen), - .mem_req_data_in (vx_mem_req_data), - .mem_req_tag_in (vx_mem_req_tag), - .mem_req_ready_in (vx_mem_req_ready_qual), - - .mem_rsp_valid_in (vx_mem_rsp_valid), - .mem_rsp_data_in (vx_mem_rsp_data), - .mem_rsp_tag_in (vx_mem_rsp_tag), - .mem_rsp_ready_in (vx_mem_rsp_ready), - - .mem_req_valid_out (cci_vx_mem_req_if[0].valid), - .mem_req_addr_out (cci_vx_mem_req_if[0].addr), - .mem_req_rw_out (cci_vx_mem_req_if[0].rw), - .mem_req_byteen_out (cci_vx_mem_req_if[0].byteen), - .mem_req_data_out (cci_vx_mem_req_if[0].data), - .mem_req_tag_out (cci_vx_mem_req_if[0].tag), - .mem_req_ready_out (cci_vx_mem_req_if[0].ready), - - .mem_rsp_valid_out (cci_vx_mem_rsp_if[0].valid), - .mem_rsp_data_out (cci_vx_mem_rsp_if[0].data), - .mem_rsp_tag_out (cci_vx_mem_rsp_if[0].tag), - .mem_rsp_ready_out (cci_vx_mem_rsp_if[0].ready) -); - -//-- -VX_mem_req_if #( - .DATA_WIDTH ($bits(t_local_mem_data)), - .ADDR_WIDTH ($bits(t_local_mem_addr)), - .TAG_WIDTH (AVS_REQ_TAGW+1) -) mem_req_if(); - -VX_mem_rsp_if #( - .DATA_WIDTH ($bits(t_local_mem_data)), - .TAG_WIDTH (AVS_REQ_TAGW+1) -) mem_rsp_if(); - -`RESET_RELAY (mem_arb_reset, reset); - -VX_mem_arb #( - .NUM_REQS (2), - .DATA_WIDTH (LMEM_DATA_WIDTH), - .ADDR_WIDTH (LMEM_ADDR_WIDTH), - .TAG_WIDTH (AVS_REQ_TAGW), - .ARBITER ("P"), - .BUFFERED_REQ (0), - .BUFFERED_RSP (0) -) mem_arb ( - .clk (clk), - .reset (mem_arb_reset), - .req_in_if (cci_vx_mem_req_if), - .rsp_in_if (cci_vx_mem_rsp_if), - .req_out_if (mem_req_if), - .rsp_out_if (mem_rsp_if) -); - -//-- - -`RESET_RELAY (avs_adapter_reset, reset); - -VX_avs_adapter #( - .DATA_WIDTH (LMEM_DATA_WIDTH), - .ADDR_WIDTH (LMEM_ADDR_WIDTH), - .BURST_WIDTH (LMEM_BURST_CTRW), - .NUM_BANKS (NUM_LOCAL_MEM_BANKS), - .TAG_WIDTH (AVS_REQ_TAGW + 1), - .RD_QUEUE_SIZE (AVS_RD_QUEUE_SIZE), - .BUFFERED_REQ (2), - .BUFFERED_RSP (0) -) avs_adapter ( - .clk (clk), - .reset (avs_adapter_reset), - - // Memory request - .mem_req_valid (mem_req_if.valid), - .mem_req_rw (mem_req_if.rw), - .mem_req_byteen (mem_req_if.byteen), - .mem_req_addr (mem_req_if.addr), - .mem_req_data (mem_req_if.data), - .mem_req_tag (mem_req_if.tag), - .mem_req_ready (mem_req_if.ready), - - // Memory response - .mem_rsp_valid (mem_rsp_if.valid), - .mem_rsp_data (mem_rsp_if.data), - .mem_rsp_tag (mem_rsp_if.tag), - .mem_rsp_ready (mem_rsp_if.ready), - - // AVS bus - .avs_writedata (avs_writedata), - .avs_readdata (avs_readdata), - .avs_address (avs_address), - .avs_waitrequest (avs_waitrequest), - .avs_write (avs_write), - .avs_read (avs_read), - .avs_byteenable (avs_byteenable), - .avs_burstcount (avs_burstcount), - .avs_readdatavalid(avs_readdatavalid) -); - -// CCI-P Read Request /////////////////////////////////////////////////////////// - -reg [CCI_ADDR_WIDTH-1:0] cci_mem_wr_req_ctr; -wire [CCI_ADDR_WIDTH-1:0] cci_mem_wr_req_addr; -reg [CCI_ADDR_WIDTH-1:0] cci_mem_wr_req_addr_base; - -wire cci_rd_req_fire; -t_ccip_clAddr cci_rd_req_addr; -reg cci_rd_req_valid, cci_rd_req_wait; -reg [CCI_ADDR_WIDTH-1:0] cci_rd_req_ctr; -wire [CCI_ADDR_WIDTH-1:0] cci_rd_req_ctr_next; -wire [CCI_RD_QUEUE_TAGW-1:0] cci_rd_req_tag; - -wire [CCI_RD_QUEUE_TAGW-1:0] cci_rd_rsp_tag; -reg [CCI_RD_QUEUE_TAGW-1:0] cci_rd_rsp_ctr; - -wire cci_rdq_push, cci_rdq_pop; -wire [CCI_RD_QUEUE_DATAW-1:0] cci_rdq_din; -wire cci_rdq_empty; - -always @(*) begin - af2cp_sTxPort.c0.valid = cci_rd_req_fire; - af2cp_sTxPort.c0.hdr = t_ccip_c0_ReqMemHdr'(0); - af2cp_sTxPort.c0.hdr.address = cci_rd_req_addr; - af2cp_sTxPort.c0.hdr.mdata = t_ccip_mdata'(cci_rd_req_tag); -end - -wire cci_mem_wr_req_fire = cci_mem_wr_req_valid && cci_mem_req_ready; - -wire cci_rd_rsp_fire = cp2af_sRxPort.c0.rspValid - && (cp2af_sRxPort.c0.hdr.resp_type == eRSP_RDLINE); - -assign cci_rd_req_tag = CCI_RD_QUEUE_TAGW'(cci_rd_req_ctr); -assign cci_rd_rsp_tag = CCI_RD_QUEUE_TAGW'(cp2af_sRxPort.c0.hdr.mdata); - -assign cci_rdq_push = cci_rd_rsp_fire; -assign cci_rdq_pop = cci_mem_wr_req_fire; -assign cci_rdq_din = {cp2af_sRxPort.c0.data, cci_mem_wr_req_addr_base + CCI_ADDR_WIDTH'(cci_rd_rsp_tag)}; - -wire [$clog2(CCI_RD_QUEUE_SIZE+1)-1:0] cci_pending_reads; -wire cci_pending_reads_full; -VX_pending_size #( - .SIZE (CCI_RD_QUEUE_SIZE) -) cci_rd_pending_size ( - .clk (clk), - .reset (reset), - .incr (cci_rd_req_fire), - .decr (cci_rdq_pop), - .full (cci_pending_reads_full), - .size (cci_pending_reads), - `UNUSED_PIN (empty) -); -`UNUSED_VAR (cci_pending_reads) - -assign cci_rd_req_ctr_next = cci_rd_req_ctr + CCI_ADDR_WIDTH'(cci_rd_req_fire ? 1 : 0); - -assign cci_rd_req_fire = cci_rd_req_valid && !(cci_rd_req_wait || cci_pending_reads_full); - -assign cci_mem_wr_req_valid = !cci_rdq_empty; - -assign cci_mem_wr_req_addr = cci_rdq_dout[CCI_ADDR_WIDTH-1:0]; - -// Send read requests to CCI -always @(posedge clk) begin - if (reset) begin - cci_rd_req_valid <= 0; - cci_rd_req_wait <= 0; - end else begin - if ((STATE_IDLE == state) - && (CMD_MEM_WRITE == cmd_type)) begin - cci_rd_req_valid <= (cmd_data_size != 0); - cci_rd_req_wait <= 0; + vx_reset_ctr <= '0; + end end - cci_rd_req_valid <= (STATE_MEM_WRITE == state) - && (cci_rd_req_ctr_next != cmd_data_size) - && !cp2af_sRxPort.c0TxAlmFull; + wire is_mmio_wr_cmd = cp2af_sRxPort.c0.mmioWrValid && (MMIO_CMD_TYPE == mmio_hdr.address); + wire [CMD_TYPE_WIDTH-1:0] cmd_type = is_mmio_wr_cmd ? + CMD_TYPE_WIDTH'(cp2af_sRxPort.c0.data) : CMD_TYPE_WIDTH'(0); - if (cci_rd_req_fire && (cci_rd_req_tag == CCI_RD_QUEUE_TAGW'(CCI_RD_WINDOW_SIZE-1))) begin - cci_rd_req_wait <= 1; // end current request batch + always @(posedge clk) begin + if (reset) begin + state <= STATE_IDLE; + vx_busy_wait <= 0; + vx_running <= 0; + end else begin + case (state) + STATE_IDLE: begin + case (cmd_type) + CMD_MEM_READ: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE MEM_READ: ia=0x%0h addr=0x%0h size=%0d\n", $time, cmd_io_addr, cmd_mem_addr, cmd_data_size)); + `endif + state <= STATE_MEM_READ; + end + CMD_MEM_WRITE: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE MEM_WRITE: ia=0x%0h addr=0x%0h size=%0d\n", $time, cmd_io_addr, cmd_mem_addr, cmd_data_size)); + `endif + state <= STATE_MEM_WRITE; + end + CMD_DCR_WRITE: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE DCR_WRITE: addr=0x%0h data=%0d\n", $time, cmd_dcr_addr, cmd_dcr_data)); + `endif + state <= STATE_DCR_WRITE; + end + CMD_RUN: begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE RUN\n", $time)); + `endif + state <= STATE_RUN; + vx_running <= 0; + end + default: begin + state <= state; + end + endcase + end + STATE_MEM_READ: begin + if (cmd_mem_rd_done) begin + state <= STATE_IDLE; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE IDLE\n", $time)); + `endif + end + end + STATE_MEM_WRITE: begin + if (cmd_mem_wr_done) begin + state <= STATE_IDLE; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE IDLE\n", $time)); + `endif + end + end + STATE_DCR_WRITE: begin + state <= STATE_IDLE; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: STATE IDLE\n", $time)); + `endif + end + STATE_RUN: begin + if (vx_running) begin + if (vx_busy_wait) begin + // wait until the gpu goes busy + if (vx_busy) begin + vx_busy_wait <= 0; + end + end else begin + // wait until the gpu is not busy + if (~vx_busy) begin + state <= STATE_IDLE; + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: AFU: End execution\n", $time)); + `TRACE(2, ("%d: STATE IDLE\n", $time)); + `endif + end + end + end else begin + // wait until the reset sequence is complete + if (vx_reset_ctr == (`RESET_DELAY-1)) begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: AFU: Begin execution\n", $time)); + `endif + vx_running <= 1; + vx_busy_wait <= 1; + end + end + end + default:; + endcase + end end - if (cci_rd_rsp_fire && (cci_rd_rsp_ctr == CCI_RD_QUEUE_TAGW'(CCI_RD_WINDOW_SIZE-1))) begin - cci_rd_req_wait <= 0; // begin new request batch - end - end + // AVS Controller ///////////////////////////////////////////////////////////// - if ((STATE_IDLE == state) - && (CMD_MEM_WRITE == cmd_type)) begin - cci_rd_req_addr <= cmd_io_addr; - cci_rd_req_ctr <= '0; - cci_rd_rsp_ctr <= '0; - cci_mem_wr_req_ctr <= '0; - cci_mem_wr_req_addr_base <= cmd_mem_addr; - cmd_mem_wr_done <= 0; - end + wire cci_mem_rd_req_valid; + wire cci_mem_wr_req_valid; + wire [CCI_RD_QUEUE_DATAW-1:0] cci_rdq_dout; - if (cci_rd_req_fire) begin - cci_rd_req_addr <= cci_rd_req_addr + 1; - cci_rd_req_ctr <= cci_rd_req_ctr + $bits(cci_rd_req_ctr)'(1); - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: CCI Rd Req: addr=0x%0h, tag=0x%0h, rem=%0d, pending=%0d\n", $time, cci_rd_req_addr, cci_rd_req_tag, (cmd_data_size - cci_rd_req_ctr - 1), cci_pending_reads)); - `endif - end + wire cci_mem_req_valid; + wire cci_mem_req_rw; + wire [CCI_ADDR_WIDTH-1:0] cci_mem_req_addr; + wire [CCI_DATA_WIDTH-1:0] cci_mem_req_data; + wire [CCI_ADDR_WIDTH-1:0] cci_mem_req_tag; + wire cci_mem_req_ready; - if (cci_rd_rsp_fire) begin - cci_rd_rsp_ctr <= cci_rd_rsp_ctr + CCI_RD_QUEUE_TAGW'(1); - if (CCI_RD_QUEUE_TAGW'(cci_rd_rsp_ctr) == CCI_RD_QUEUE_TAGW'(CCI_RD_WINDOW_SIZE-1)) begin - cci_mem_wr_req_addr_base <= cci_mem_wr_req_addr_base + CCI_ADDR_WIDTH'(CCI_RD_WINDOW_SIZE); + wire cci_mem_rsp_valid; + wire [CCI_DATA_WIDTH-1:0] cci_mem_rsp_data; + wire [CCI_ADDR_WIDTH-1:0] cci_mem_rsp_tag; + wire cci_mem_rsp_ready; + + //-- + + VX_mem_req_if #( + .DATA_WIDTH ($bits(t_local_mem_data)), + .ADDR_WIDTH ($bits(t_local_mem_addr)), + .TAG_WIDTH (AVS_REQ_TAGW) + ) cci_vx_mem_req_if[1:0](); + + VX_mem_rsp_if #( + .DATA_WIDTH ($bits(t_local_mem_data)), + .TAG_WIDTH (AVS_REQ_TAGW) + ) cci_vx_mem_rsp_if[1:0](); + + VX_mem_adapter #( + .SRC_DATA_WIDTH (CCI_DATA_WIDTH), + .DST_DATA_WIDTH (LMEM_DATA_WIDTH), + .SRC_ADDR_WIDTH (CCI_ADDR_WIDTH), + .DST_ADDR_WIDTH (LMEM_ADDR_WIDTH), + .SRC_TAG_WIDTH (CCI_ADDR_WIDTH), + .DST_TAG_WIDTH (AVS_REQ_TAGW), + .BUFFERED_REQ (0), + .BUFFERED_RSP (0) + ) cci_mem_adapter ( + .clk (clk), + .reset (reset), + + .mem_req_valid_in (cci_mem_req_valid), + .mem_req_addr_in (cci_mem_req_addr), + .mem_req_rw_in (cci_mem_req_rw), + .mem_req_byteen_in ({CCI_DATA_SIZE{1'b1}}), + .mem_req_data_in (cci_mem_req_data), + .mem_req_tag_in (cci_mem_req_tag), + .mem_req_ready_in (cci_mem_req_ready), + + .mem_rsp_valid_in (cci_mem_rsp_valid), + .mem_rsp_data_in (cci_mem_rsp_data), + .mem_rsp_tag_in (cci_mem_rsp_tag), + .mem_rsp_ready_in (cci_mem_rsp_ready), + + .mem_req_valid_out (cci_vx_mem_req_if[1].valid), + .mem_req_addr_out (cci_vx_mem_req_if[1].addr), + .mem_req_rw_out (cci_vx_mem_req_if[1].rw), + .mem_req_byteen_out (cci_vx_mem_req_if[1].byteen), + .mem_req_data_out (cci_vx_mem_req_if[1].data), + .mem_req_tag_out (cci_vx_mem_req_if[1].tag), + .mem_req_ready_out (cci_vx_mem_req_if[1].ready), + + .mem_rsp_valid_out (cci_vx_mem_rsp_if[1].valid), + .mem_rsp_data_out (cci_vx_mem_rsp_if[1].data), + .mem_rsp_tag_out (cci_vx_mem_rsp_if[1].tag), + .mem_rsp_ready_out (cci_vx_mem_rsp_if[1].ready) + ); + + //-- + + wire vx_mem_is_cout; + wire vx_mem_req_valid_qual; + wire vx_mem_req_ready_qual; + + assign vx_mem_req_valid_qual = vx_mem_req_valid && ~vx_mem_is_cout; + + VX_mem_adapter #( + .SRC_DATA_WIDTH (`VX_MEM_DATA_WIDTH), + .DST_DATA_WIDTH (LMEM_DATA_WIDTH), + .SRC_ADDR_WIDTH (`VX_MEM_ADDR_WIDTH), + .DST_ADDR_WIDTH (LMEM_ADDR_WIDTH), + .SRC_TAG_WIDTH (`VX_MEM_TAG_WIDTH), + .DST_TAG_WIDTH (AVS_REQ_TAGW), + .BUFFERED_REQ (0), + .BUFFERED_RSP (2) + ) vx_mem_adapter ( + .clk (clk), + .reset (reset), + + .mem_req_valid_in (vx_mem_req_valid_qual), + .mem_req_addr_in (vx_mem_req_addr), + .mem_req_rw_in (vx_mem_req_rw), + .mem_req_byteen_in (vx_mem_req_byteen), + .mem_req_data_in (vx_mem_req_data), + .mem_req_tag_in (vx_mem_req_tag), + .mem_req_ready_in (vx_mem_req_ready_qual), + + .mem_rsp_valid_in (vx_mem_rsp_valid), + .mem_rsp_data_in (vx_mem_rsp_data), + .mem_rsp_tag_in (vx_mem_rsp_tag), + .mem_rsp_ready_in (vx_mem_rsp_ready), + + .mem_req_valid_out (cci_vx_mem_req_if[0].valid), + .mem_req_addr_out (cci_vx_mem_req_if[0].addr), + .mem_req_rw_out (cci_vx_mem_req_if[0].rw), + .mem_req_byteen_out (cci_vx_mem_req_if[0].byteen), + .mem_req_data_out (cci_vx_mem_req_if[0].data), + .mem_req_tag_out (cci_vx_mem_req_if[0].tag), + .mem_req_ready_out (cci_vx_mem_req_if[0].ready), + + .mem_rsp_valid_out (cci_vx_mem_rsp_if[0].valid), + .mem_rsp_data_out (cci_vx_mem_rsp_if[0].data), + .mem_rsp_tag_out (cci_vx_mem_rsp_if[0].tag), + .mem_rsp_ready_out (cci_vx_mem_rsp_if[0].ready) + ); + + //-- + VX_mem_req_if #( + .DATA_WIDTH ($bits(t_local_mem_data)), + .ADDR_WIDTH ($bits(t_local_mem_addr)), + .TAG_WIDTH (AVS_REQ_TAGW+1) + ) mem_req_if(); + + VX_mem_rsp_if #( + .DATA_WIDTH ($bits(t_local_mem_data)), + .TAG_WIDTH (AVS_REQ_TAGW+1) + ) mem_rsp_if(); + + `RESET_RELAY (mem_arb_reset, reset); + + VX_mem_arb #( + .NUM_REQS (2), + .DATA_WIDTH (LMEM_DATA_WIDTH), + .ADDR_WIDTH (LMEM_ADDR_WIDTH), + .TAG_WIDTH (AVS_REQ_TAGW), + .ARBITER ("P"), + .BUFFERED_REQ (0), + .BUFFERED_RSP (0) + ) mem_arb ( + .clk (clk), + .reset (mem_arb_reset), + .req_in_if (cci_vx_mem_req_if), + .rsp_in_if (cci_vx_mem_rsp_if), + .req_out_if (mem_req_if), + .rsp_out_if (mem_rsp_if) + ); + + //-- + + `RESET_RELAY (avs_adapter_reset, reset); + + VX_avs_adapter #( + .DATA_WIDTH (LMEM_DATA_WIDTH), + .ADDR_WIDTH (LMEM_ADDR_WIDTH), + .BURST_WIDTH (LMEM_BURST_CTRW), + .NUM_BANKS (NUM_LOCAL_MEM_BANKS), + .TAG_WIDTH (AVS_REQ_TAGW + 1), + .RD_QUEUE_SIZE (AVS_RD_QUEUE_SIZE), + .BUFFERED_REQ (2), + .BUFFERED_RSP (0) + ) avs_adapter ( + .clk (clk), + .reset (avs_adapter_reset), + + // Memory request + .mem_req_valid (mem_req_if.valid), + .mem_req_rw (mem_req_if.rw), + .mem_req_byteen (mem_req_if.byteen), + .mem_req_addr (mem_req_if.addr), + .mem_req_data (mem_req_if.data), + .mem_req_tag (mem_req_if.tag), + .mem_req_ready (mem_req_if.ready), + + // Memory response + .mem_rsp_valid (mem_rsp_if.valid), + .mem_rsp_data (mem_rsp_if.data), + .mem_rsp_tag (mem_rsp_if.tag), + .mem_rsp_ready (mem_rsp_if.ready), + + // AVS bus + .avs_writedata (avs_writedata), + .avs_readdata (avs_readdata), + .avs_address (avs_address), + .avs_waitrequest (avs_waitrequest), + .avs_write (avs_write), + .avs_read (avs_read), + .avs_byteenable (avs_byteenable), + .avs_burstcount (avs_burstcount), + .avs_readdatavalid(avs_readdatavalid) + ); + + // CCI-P Read Request /////////////////////////////////////////////////////////// + + reg [CCI_ADDR_WIDTH-1:0] cci_mem_wr_req_ctr; + wire [CCI_ADDR_WIDTH-1:0] cci_mem_wr_req_addr; + reg [CCI_ADDR_WIDTH-1:0] cci_mem_wr_req_addr_base; + + wire cci_rd_req_fire; + t_ccip_clAddr cci_rd_req_addr; + reg cci_rd_req_valid, cci_rd_req_wait; + reg [CCI_ADDR_WIDTH-1:0] cci_rd_req_ctr; + wire [CCI_ADDR_WIDTH-1:0] cci_rd_req_ctr_next; + wire [CCI_RD_QUEUE_TAGW-1:0] cci_rd_req_tag; + + wire [CCI_RD_QUEUE_TAGW-1:0] cci_rd_rsp_tag; + reg [CCI_RD_QUEUE_TAGW-1:0] cci_rd_rsp_ctr; + + wire cci_rdq_push, cci_rdq_pop; + wire [CCI_RD_QUEUE_DATAW-1:0] cci_rdq_din; + wire cci_rdq_empty; + + always @(*) begin + af2cp_sTxPort.c0.valid = cci_rd_req_fire; + af2cp_sTxPort.c0.hdr = t_ccip_c0_ReqMemHdr'(0); + af2cp_sTxPort.c0.hdr.address = cci_rd_req_addr; + af2cp_sTxPort.c0.hdr.mdata = t_ccip_mdata'(cci_rd_req_tag); end - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: CCI Rd Rsp: idx=%0d, ctr=%0d, data=0x%0h\n", $time, cci_rd_rsp_tag, cci_rd_rsp_ctr, cp2af_sRxPort.c0.data)); - `endif - end - if (cci_rdq_pop) begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: CCI Rd Queue Pop: pending=%0d\n", $time, cci_pending_reads)); - `endif - end + wire cci_mem_wr_req_fire = cci_mem_wr_req_valid && cci_mem_req_ready; - if (cci_mem_wr_req_fire) begin - cci_mem_wr_req_ctr <= cci_mem_wr_req_ctr + CCI_ADDR_WIDTH'(1); - if (cci_mem_wr_req_ctr == (cmd_data_size-1)) begin - cmd_mem_wr_done <= 1; + wire cci_rd_rsp_fire = cp2af_sRxPort.c0.rspValid + && (cp2af_sRxPort.c0.hdr.resp_type == eRSP_RDLINE); + + assign cci_rd_req_tag = CCI_RD_QUEUE_TAGW'(cci_rd_req_ctr); + assign cci_rd_rsp_tag = CCI_RD_QUEUE_TAGW'(cp2af_sRxPort.c0.hdr.mdata); + + assign cci_rdq_push = cci_rd_rsp_fire; + assign cci_rdq_pop = cci_mem_wr_req_fire; + assign cci_rdq_din = {cp2af_sRxPort.c0.data, cci_mem_wr_req_addr_base + CCI_ADDR_WIDTH'(cci_rd_rsp_tag)}; + + wire [$clog2(CCI_RD_QUEUE_SIZE+1)-1:0] cci_pending_reads; + wire cci_pending_reads_full; + VX_pending_size #( + .SIZE (CCI_RD_QUEUE_SIZE) + ) cci_rd_pending_size ( + .clk (clk), + .reset (reset), + .incr (cci_rd_req_fire), + .decr (cci_rdq_pop), + .full (cci_pending_reads_full), + .size (cci_pending_reads), + `UNUSED_PIN (empty) + ); + + `UNUSED_VAR (cci_pending_reads) + + assign cci_rd_req_ctr_next = cci_rd_req_ctr + CCI_ADDR_WIDTH'(cci_rd_req_fire ? 1 : 0); + + assign cci_rd_req_fire = cci_rd_req_valid && !(cci_rd_req_wait || cci_pending_reads_full); + + assign cci_mem_wr_req_valid = !cci_rdq_empty; + + assign cci_mem_wr_req_addr = cci_rdq_dout[CCI_ADDR_WIDTH-1:0]; + + // Send read requests to CCI + always @(posedge clk) begin + if (reset) begin + cci_rd_req_valid <= 0; + cci_rd_req_wait <= 0; + end else begin + if ((STATE_IDLE == state) + && (CMD_MEM_WRITE == cmd_type)) begin + cci_rd_req_valid <= (cmd_data_size != 0); + cci_rd_req_wait <= 0; + end + + cci_rd_req_valid <= (STATE_MEM_WRITE == state) + && (cci_rd_req_ctr_next != cmd_data_size) + && !cp2af_sRxPort.c0TxAlmFull; + + if (cci_rd_req_fire + && (cci_rd_req_tag == CCI_RD_QUEUE_TAGW'(CCI_RD_WINDOW_SIZE-1))) begin + cci_rd_req_wait <= 1; // end current request batch + end + + if (cci_rd_rsp_fire + && (cci_rd_rsp_ctr == CCI_RD_QUEUE_TAGW'(CCI_RD_WINDOW_SIZE-1))) begin + cci_rd_req_wait <= 0; // begin new request batch + end + end + + if ((STATE_IDLE == state) + && (CMD_MEM_WRITE == cmd_type)) begin + cci_rd_req_addr <= cmd_io_addr; + cci_rd_req_ctr <= '0; + cci_rd_rsp_ctr <= '0; + cci_mem_wr_req_ctr <= '0; + cci_mem_wr_req_addr_base <= cmd_mem_addr; + cmd_mem_wr_done <= 0; + end + + if (cci_rd_req_fire) begin + cci_rd_req_addr <= cci_rd_req_addr + 1; + cci_rd_req_ctr <= cci_rd_req_ctr + $bits(cci_rd_req_ctr)'(1); + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: CCI Rd Req: addr=0x%0h, tag=0x%0h, rem=%0d, pending=%0d\n", $time, cci_rd_req_addr, cci_rd_req_tag, (cmd_data_size - cci_rd_req_ctr - 1), cci_pending_reads)); + `endif + end + + if (cci_rd_rsp_fire) begin + cci_rd_rsp_ctr <= cci_rd_rsp_ctr + CCI_RD_QUEUE_TAGW'(1); + if (CCI_RD_QUEUE_TAGW'(cci_rd_rsp_ctr) == CCI_RD_QUEUE_TAGW'(CCI_RD_WINDOW_SIZE-1)) begin + cci_mem_wr_req_addr_base <= cci_mem_wr_req_addr_base + CCI_ADDR_WIDTH'(CCI_RD_WINDOW_SIZE); + end + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: CCI Rd Rsp: idx=%0d, ctr=%0d, data=0x%0h\n", $time, cci_rd_rsp_tag, cci_rd_rsp_ctr, cp2af_sRxPort.c0.data)); + `endif + end + + if (cci_rdq_pop) begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: CCI Rd Queue Pop: pending=%0d\n", $time, cci_pending_reads)); + `endif + end + + if (cci_mem_wr_req_fire) begin + cci_mem_wr_req_ctr <= cci_mem_wr_req_ctr + CCI_ADDR_WIDTH'(1); + if (cci_mem_wr_req_ctr == (cmd_data_size-1)) begin + cmd_mem_wr_done <= 1; + end + end end - end -end -`RESET_RELAY (cci_rdq_reset, reset); + `RESET_RELAY (cci_rdq_reset, reset); -VX_fifo_queue #( - .DATAW (CCI_RD_QUEUE_DATAW), - .DEPTH (CCI_RD_QUEUE_SIZE), - .OUT_REG (1) -) cci_rd_req_queue ( - .clk (clk), - .reset (cci_rdq_reset), - .push (cci_rdq_push), - .pop (cci_rdq_pop), - .data_in (cci_rdq_din), - .data_out (cci_rdq_dout), - .empty (cci_rdq_empty), - `UNUSED_PIN (full), - `UNUSED_PIN (alm_empty), - `UNUSED_PIN (alm_full), - `UNUSED_PIN (size) -); + VX_fifo_queue #( + .DATAW (CCI_RD_QUEUE_DATAW), + .DEPTH (CCI_RD_QUEUE_SIZE), + .OUT_REG (1) + ) cci_rd_req_queue ( + .clk (clk), + .reset (cci_rdq_reset), + .push (cci_rdq_push), + .pop (cci_rdq_pop), + .data_in (cci_rdq_din), + .data_out (cci_rdq_dout), + .empty (cci_rdq_empty), + `UNUSED_PIN (full), + `UNUSED_PIN (alm_empty), + `UNUSED_PIN (alm_full), + `UNUSED_PIN (size) + ); `DEBUG_BLOCK( - reg [CCI_RD_WINDOW_SIZE-1:0] dbg_cci_rd_rsp_mask; - always @(posedge clk) begin - if (reset) begin - dbg_cci_rd_rsp_mask <= '0; - end else begin - if (cci_rd_rsp_fire) begin - if (cci_rd_rsp_ctr == 0) begin - dbg_cci_rd_rsp_mask <= (CCI_RD_WINDOW_SIZE'(1) << cci_rd_rsp_tag); - end else begin - assert(!dbg_cci_rd_rsp_mask[cci_rd_rsp_tag]); - dbg_cci_rd_rsp_mask[cci_rd_rsp_tag] <= 1; - end - end + reg [CCI_RD_WINDOW_SIZE-1:0] dbg_cci_rd_rsp_mask; + always @(posedge clk) begin + if (reset) begin + dbg_cci_rd_rsp_mask <= '0; + end else begin + if (cci_rd_rsp_fire) begin + if (cci_rd_rsp_ctr == 0) begin + dbg_cci_rd_rsp_mask <= (CCI_RD_WINDOW_SIZE'(1) << cci_rd_rsp_tag); + end else begin + assert(!dbg_cci_rd_rsp_mask[cci_rd_rsp_tag]); + dbg_cci_rd_rsp_mask[cci_rd_rsp_tag] <= 1; + end + end + end end - end ) -// CCI-P Write Request ////////////////////////////////////////////////////////// + // CCI-P Write Request ////////////////////////////////////////////////////////// -reg [CCI_ADDR_WIDTH-1:0] cci_mem_rd_req_ctr; -reg [CCI_ADDR_WIDTH-1:0] cci_mem_rd_req_addr; -reg cci_mem_rd_req_done; + reg [CCI_ADDR_WIDTH-1:0] cci_mem_rd_req_ctr; + reg [CCI_ADDR_WIDTH-1:0] cci_mem_rd_req_addr; + reg cci_mem_rd_req_done; -reg [CCI_ADDR_WIDTH-1:0] cci_wr_req_ctr; -reg cci_wr_req_fire; -t_ccip_clAddr cci_wr_req_addr; -t_ccip_clData cci_wr_req_data; -reg cci_wr_req_done; + reg [CCI_ADDR_WIDTH-1:0] cci_wr_req_ctr; + reg cci_wr_req_fire; + t_ccip_clAddr cci_wr_req_addr; + t_ccip_clData cci_wr_req_data; + reg cci_wr_req_done; -always @(*) begin - af2cp_sTxPort.c1.valid = cci_wr_req_fire; - af2cp_sTxPort.c1.hdr = t_ccip_c1_ReqMemHdr'(0); - af2cp_sTxPort.c1.hdr.sop = 1; // single line write mode - af2cp_sTxPort.c1.hdr.address = cci_wr_req_addr; - af2cp_sTxPort.c1.data = cci_wr_req_data; -end + always @(*) begin + af2cp_sTxPort.c1.valid = cci_wr_req_fire; + af2cp_sTxPort.c1.hdr = t_ccip_c1_ReqMemHdr'(0); + af2cp_sTxPort.c1.hdr.sop = 1; // single line write mode + af2cp_sTxPort.c1.hdr.address = cci_wr_req_addr; + af2cp_sTxPort.c1.data = cci_wr_req_data; + end -wire cci_mem_rd_req_fire = cci_mem_rd_req_valid && cci_mem_req_ready; -wire cci_mem_rd_rsp_fire = cci_mem_rsp_valid && cci_mem_rsp_ready; + wire cci_mem_rd_req_fire = cci_mem_rd_req_valid && cci_mem_req_ready; + wire cci_mem_rd_rsp_fire = cci_mem_rsp_valid && cci_mem_rsp_ready; -wire cci_wr_rsp_fire = (STATE_MEM_READ == state) - && cp2af_sRxPort.c1.rspValid - && (cp2af_sRxPort.c1.hdr.resp_type == eRSP_WRLINE); + wire cci_wr_rsp_fire = (STATE_MEM_READ == state) + && cp2af_sRxPort.c1.rspValid + && (cp2af_sRxPort.c1.hdr.resp_type == eRSP_WRLINE); -wire [$clog2(CCI_RW_PENDING_SIZE+1)-1:0] cci_pending_writes; -wire cci_pending_writes_empty; -wire cci_pending_writes_full; + wire [$clog2(CCI_RW_PENDING_SIZE+1)-1:0] cci_pending_writes; + wire cci_pending_writes_empty; + wire cci_pending_writes_full; -VX_pending_size #( - .SIZE (CCI_RW_PENDING_SIZE) -) cci_wr_pending_size ( - .clk (clk), - .reset (reset), - .incr (cci_mem_rd_rsp_fire), - .decr (cci_wr_rsp_fire), - .empty (cci_pending_writes_empty), - .full (cci_pending_writes_full), - .size (cci_pending_writes) -); -`UNUSED_VAR (cci_pending_writes) + VX_pending_size #( + .SIZE (CCI_RW_PENDING_SIZE) + ) cci_wr_pending_size ( + .clk (clk), + .reset (reset), + .incr (cci_mem_rd_rsp_fire), + .decr (cci_wr_rsp_fire), + .empty (cci_pending_writes_empty), + .full (cci_pending_writes_full), + .size (cci_pending_writes) + ); -assign cci_mem_rd_req_valid = (STATE_MEM_READ == state) - && !cci_mem_rd_req_done; + `UNUSED_VAR (cci_pending_writes) -assign cci_mem_rsp_ready = !cp2af_sRxPort.c1TxAlmFull - && !cci_pending_writes_full; + assign cci_mem_rd_req_valid = (STATE_MEM_READ == state) + && ~cci_mem_rd_req_done; -assign cmd_mem_rd_done = cci_wr_req_done - && cci_pending_writes_empty; + assign cci_mem_rsp_ready = ~cp2af_sRxPort.c1TxAlmFull + && ~cci_pending_writes_full; -// Send write requests to CCI -always @(posedge clk) begin - if (reset) begin - cci_wr_req_fire <= 0; - end else begin - cci_wr_req_fire <= cci_mem_rd_rsp_fire; - end - - if ((STATE_IDLE == state) - && (CMD_MEM_READ == cmd_type)) begin - cci_mem_rd_req_ctr <= '0; - cci_mem_rd_req_addr <= cmd_mem_addr; - cci_mem_rd_req_done <= 0; - cci_wr_req_ctr <= cmd_data_size; - cci_wr_req_done <= 0; - end + assign cmd_mem_rd_done = cci_wr_req_done + && cci_pending_writes_empty; - if (cci_mem_rd_req_fire) begin - cci_mem_rd_req_addr <= cci_mem_rd_req_addr + CCI_ADDR_WIDTH'(1); - cci_mem_rd_req_ctr <= cci_mem_rd_req_ctr + CCI_ADDR_WIDTH'(1); - if (cci_mem_rd_req_ctr == (cmd_data_size-1)) begin - cci_mem_rd_req_done <= 1; - end - end + // Send write requests to CCI + always @(posedge clk) begin + if (reset) begin + cci_wr_req_fire <= 0; + end else begin + cci_wr_req_fire <= cci_mem_rd_rsp_fire; + end + + if ((STATE_IDLE == state) + && (CMD_MEM_READ == cmd_type)) begin + cci_mem_rd_req_ctr <= '0; + cci_mem_rd_req_addr <= cmd_mem_addr; + cci_mem_rd_req_done <= 0; + cci_wr_req_ctr <= cmd_data_size; + cci_wr_req_done <= 0; + end - cci_wr_req_addr <= cmd_io_addr + t_ccip_clAddr'(cci_mem_rsp_tag); - cci_wr_req_data <= t_ccip_clData'(cci_mem_rsp_data); + if (cci_mem_rd_req_fire) begin + cci_mem_rd_req_addr <= cci_mem_rd_req_addr + CCI_ADDR_WIDTH'(1); + cci_mem_rd_req_ctr <= cci_mem_rd_req_ctr + CCI_ADDR_WIDTH'(1); + if (cci_mem_rd_req_ctr == (cmd_data_size-1)) begin + cci_mem_rd_req_done <= 1; + end + end - if (cci_wr_req_fire) begin - `ASSERT(cci_wr_req_ctr != 0, ("runtime error")); - cci_wr_req_ctr <= cci_wr_req_ctr - CCI_ADDR_WIDTH'(1); - if (cci_wr_req_ctr == CCI_ADDR_WIDTH'(1)) begin - cci_wr_req_done <= 1; + cci_wr_req_addr <= cmd_io_addr + t_ccip_clAddr'(cci_mem_rsp_tag); + cci_wr_req_data <= t_ccip_clData'(cci_mem_rsp_data); + + if (cci_wr_req_fire) begin + `ASSERT(cci_wr_req_ctr != 0, ("runtime error")); + cci_wr_req_ctr <= cci_wr_req_ctr - CCI_ADDR_WIDTH'(1); + if (cci_wr_req_ctr == CCI_ADDR_WIDTH'(1)) begin + cci_wr_req_done <= 1; + end + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: CCI Wr Req: addr=0x%0h, rem=%0d, pending=%0d, data=0x%0h\n", $time, cci_wr_req_addr, (cci_wr_req_ctr - 1), cci_pending_writes, af2cp_sTxPort.c1.data)); + `endif + end + + if (cci_wr_rsp_fire) begin + `ifdef DBG_TRACE_AFU + `TRACE(2, ("%d: CCI Wr Rsp: pending=%0d\n", $time, cci_pending_writes)); + `endif + end end - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: CCI Wr Req: addr=0x%0h, rem=%0d, pending=%0d, data=0x%0h\n", $time, cci_wr_req_addr, (cci_wr_req_ctr - 1), cci_pending_writes, af2cp_sTxPort.c1.data)); - `endif - end - if (cci_wr_rsp_fire) begin - `ifdef DBG_TRACE_AFU - `TRACE(2, ("%d: CCI Wr Rsp: pending=%0d\n", $time, cci_pending_writes)); - `endif - end -end + //-- -//-- + assign cci_mem_req_rw = state[0]; + `STATIC_ASSERT(STATE_MEM_WRITE == 1, ("invalid value")); // 01 + `STATIC_ASSERT(STATE_MEM_READ == 2, ("invalid value")); // 10 -assign cci_mem_req_rw = state[0]; -`STATIC_ASSERT(STATE_MEM_WRITE == 1, ("invalid value")); // 01 -`STATIC_ASSERT(STATE_MEM_READ == 2, ("invalid value")); // 10 + assign cci_mem_req_valid = cci_mem_req_rw ? cci_mem_wr_req_valid : cci_mem_rd_req_valid; + assign cci_mem_req_addr = cci_mem_req_rw ? cci_mem_wr_req_addr : cci_mem_rd_req_addr; + assign cci_mem_req_data = cci_rdq_dout[CCI_RD_QUEUE_DATAW-1:CCI_ADDR_WIDTH]; + assign cci_mem_req_tag = cci_mem_req_rw ? cci_mem_wr_req_ctr : cci_mem_rd_req_ctr; -assign cci_mem_req_valid = cci_mem_req_rw ? cci_mem_wr_req_valid : cci_mem_rd_req_valid; -assign cci_mem_req_addr = cci_mem_req_rw ? cci_mem_wr_req_addr : cci_mem_rd_req_addr; -assign cci_mem_req_data = cci_rdq_dout[CCI_RD_QUEUE_DATAW-1:CCI_ADDR_WIDTH]; -assign cci_mem_req_tag = cci_mem_req_rw ? cci_mem_wr_req_ctr : cci_mem_rd_req_ctr; + // Vortex /////////////////////////////////////////////////////////////////// -// Vortex ///////////////////////////////////////////////////////////////////// + wire vx_dcr_wr_valid = (STATE_DCR_WRITE == state); + wire [`VX_DCR_ADDR_WIDTH-1:0] vx_dcr_wr_addr = cmd_dcr_addr; + wire [`VX_DCR_DATA_WIDTH-1:0] vx_dcr_wr_data = cmd_dcr_data; + + `SCOPE_IO_SWITCH (2) -wire vx_dcr_wr_valid = (STATE_DCR_WRITE == state); -wire [`VX_DCR_ADDR_WIDTH-1:0] vx_dcr_wr_addr = cmd_dcr_addr; -wire [`VX_DCR_DATA_WIDTH-1:0] vx_dcr_wr_data = cmd_dcr_data; + Vortex vortex ( + `SCOPE_IO_BIND (1) -Vortex vortex ( - `SCOPE_BIND_afu_vortex + .clk (clk), + .reset (reset || ~vx_running), - .clk (clk), - .reset (reset || ~vx_running), + // Memory request + .mem_req_valid (vx_mem_req_valid), + .mem_req_rw (vx_mem_req_rw), + .mem_req_byteen (vx_mem_req_byteen), + .mem_req_addr (vx_mem_req_addr), + .mem_req_data (vx_mem_req_data), + .mem_req_tag (vx_mem_req_tag), + .mem_req_ready (vx_mem_req_ready), - // Memory request - .mem_req_valid (vx_mem_req_valid), - .mem_req_rw (vx_mem_req_rw), - .mem_req_byteen (vx_mem_req_byteen), - .mem_req_addr (vx_mem_req_addr), - .mem_req_data (vx_mem_req_data), - .mem_req_tag (vx_mem_req_tag), - .mem_req_ready (vx_mem_req_ready), + // Memory response + .mem_rsp_valid (vx_mem_rsp_valid), + .mem_rsp_data (vx_mem_rsp_data), + .mem_rsp_tag (vx_mem_rsp_tag), + .mem_rsp_ready (vx_mem_rsp_ready), - // Memory response - .mem_rsp_valid (vx_mem_rsp_valid), - .mem_rsp_data (vx_mem_rsp_data), - .mem_rsp_tag (vx_mem_rsp_tag), - .mem_rsp_ready (vx_mem_rsp_ready), + // DCR write request + .dcr_wr_valid (vx_dcr_wr_valid), + .dcr_wr_addr (vx_dcr_wr_addr), + .dcr_wr_data (vx_dcr_wr_data), + + // Status + .busy (vx_busy) + ); - // DCR write request - .dcr_wr_valid (vx_dcr_wr_valid), - .dcr_wr_addr (vx_dcr_wr_addr), - .dcr_wr_data (vx_dcr_wr_data), - - // Status - .busy (vx_busy) -); + // COUT HANDLING ////////////////////////////////////////////////////////////// -// COUT HANDLING ////////////////////////////////////////////////////////////// + wire [COUT_TID_WIDTH-1:0] cout_tid; -wire [COUT_TID_WIDTH-1:0] cout_tid; + VX_onehot_encoder #( + .N (`VX_MEM_BYTEEN_WIDTH) + ) cout_tid_enc ( + .data_in (vx_mem_req_byteen), + .data_out (cout_tid), + `UNUSED_PIN (valid_out) + ); -VX_onehot_encoder #( - .N (`VX_MEM_BYTEEN_WIDTH) -) cout_tid_enc ( - .data_in (vx_mem_req_byteen), - .data_out (cout_tid), - `UNUSED_PIN (valid_out) -); + assign vx_mem_is_cout = (vx_mem_req_addr == `VX_MEM_ADDR_WIDTH'(`IO_COUT_ADDR >> (32 - `VX_MEM_ADDR_WIDTH))); -assign vx_mem_is_cout = (vx_mem_req_addr == `VX_MEM_ADDR_WIDTH'(`IO_COUT_ADDR >> (32 - `VX_MEM_ADDR_WIDTH))); + assign vx_mem_req_ready = vx_mem_is_cout ? ~cout_q_full : vx_mem_req_ready_qual; -assign vx_mem_req_ready = vx_mem_is_cout ? ~cout_q_full : vx_mem_req_ready_qual; + wire [`VX_MEM_BYTEEN_WIDTH-1:0][7:0] vx_mem_req_data_m = vx_mem_req_data; -wire [`VX_MEM_BYTEEN_WIDTH-1:0][7:0] vx_mem_req_data_m = vx_mem_req_data; + wire [7:0] cout_char = vx_mem_req_data_m[cout_tid]; -wire [7:0] cout_char = vx_mem_req_data_m[cout_tid]; + wire cout_q_push = vx_mem_req_valid && vx_mem_is_cout && ~cout_q_full; -wire cout_q_push = vx_mem_req_valid && vx_mem_is_cout && ~cout_q_full; + wire cout_q_pop = cp2af_sRxPort.c0.mmioRdValid + && (mmio_hdr.address == MMIO_STATUS) + && ~cout_q_empty; -wire cout_q_pop = cp2af_sRxPort.c0.mmioRdValid - && (mmio_hdr.address == MMIO_STATUS) - && ~cout_q_empty; + VX_fifo_queue #( + .DATAW (COUT_QUEUE_DATAW), + .DEPTH (COUT_QUEUE_SIZE) + ) cout_queue ( + .clk (clk), + .reset (reset), + .push (cout_q_push), + .pop (cout_q_pop), + .data_in ({cout_tid, cout_char}), + .data_out (cout_q_dout), + .empty (cout_q_empty), + .full (cout_q_full), + `UNUSED_PIN (alm_empty), + `UNUSED_PIN (alm_full), + `UNUSED_PIN (size) + ); -VX_fifo_queue #( - .DATAW (COUT_QUEUE_DATAW), - .DEPTH (COUT_QUEUE_SIZE) -) cout_queue ( - .clk (clk), - .reset (reset), - .push (cout_q_push), - .pop (cout_q_pop), - .data_in ({cout_tid, cout_char}), - .data_out (cout_q_dout), - .empty (cout_q_empty), - .full (cout_q_full), - `UNUSED_PIN (alm_empty), - `UNUSED_PIN (alm_full), - `UNUSED_PIN (size) -); - -// SCOPE ////////////////////////////////////////////////////////////////////// + // SCOPE ////////////////////////////////////////////////////////////////////// `ifdef SCOPE -`SCOPE_ASSIGN (cmd_type, cmd_type); -`SCOPE_ASSIGN (state, state); -`SCOPE_ASSIGN (cci_sRxPort_c0_mmioRdValid, cp2af_sRxPort.c0.mmioRdValid); -`SCOPE_ASSIGN (cci_sRxPort_c0_mmioWrValid, cp2af_sRxPort.c0.mmioWrValid); -`SCOPE_ASSIGN (mmio_hdr_address, mmio_hdr.address); -`SCOPE_ASSIGN (mmio_hdr_length, mmio_hdr.length); -`SCOPE_ASSIGN (cci_sRxPort_c0_hdr_mdata, cp2af_sRxPort.c0.hdr.mdata); -`SCOPE_ASSIGN (cci_sRxPort_c0_rspValid, cp2af_sRxPort.c0.rspValid); -`SCOPE_ASSIGN (cci_sRxPort_c1_rspValid, cp2af_sRxPort.c1.rspValid); -`SCOPE_ASSIGN (cci_sTxPort_c0_valid, af2cp_sTxPort.c0.valid); -`SCOPE_ASSIGN (cci_sTxPort_c0_hdr_address, af2cp_sTxPort.c0.hdr.address); -`SCOPE_ASSIGN (cci_sTxPort_c0_hdr_mdata, af2cp_sTxPort.c0.hdr.mdata); -`SCOPE_ASSIGN (cci_sTxPort_c1_valid, af2cp_sTxPort.c1.valid); -`SCOPE_ASSIGN (cci_sTxPort_c1_hdr_address, af2cp_sTxPort.c1.hdr.address); -`SCOPE_ASSIGN (cci_sTxPort_c2_mmioRdValid, af2cp_sTxPort.c2.mmioRdValid); -`SCOPE_ASSIGN (cci_sRxPort_c0TxAlmFull, cp2af_sRxPort.c0TxAlmFull); -`SCOPE_ASSIGN (cci_sRxPort_c1TxAlmFull, cp2af_sRxPort.c1TxAlmFull); -`SCOPE_ASSIGN (avs_address, avs_address[0]); -`SCOPE_ASSIGN (avs_waitrequest, avs_waitrequest[0]); -`SCOPE_ASSIGN (avs_write_fire, avs_write[0] && !avs_waitrequest[0]); -`SCOPE_ASSIGN (avs_read_fire, avs_read[0] && !avs_waitrequest[0]); -`SCOPE_ASSIGN (avs_byteenable, avs_byteenable[0]); -`SCOPE_ASSIGN (avs_burstcount, avs_burstcount[0]); -`SCOPE_ASSIGN (avs_readdatavalid, avs_readdatavalid[0]); -`SCOPE_ASSIGN (cci_mem_rd_req_ctr, cci_mem_rd_req_ctr); -`SCOPE_ASSIGN (cci_mem_wr_req_ctr, cci_mem_wr_req_ctr); -`SCOPE_ASSIGN (cci_rd_req_ctr, cci_rd_req_ctr); -`SCOPE_ASSIGN (cci_rd_rsp_ctr, cci_rd_rsp_ctr); -`SCOPE_ASSIGN (cci_wr_req_ctr, cci_wr_req_ctr); -`SCOPE_ASSIGN (cci_wr_req_fire, cci_wr_req_fire); -`SCOPE_ASSIGN (cci_wr_rsp_fire, cci_wr_rsp_fire); -`SCOPE_ASSIGN (cci_rd_req_fire, cci_rd_req_fire); -`SCOPE_ASSIGN (cci_rd_rsp_fire, cci_rd_rsp_fire); -`SCOPE_ASSIGN (cci_pending_reads_full, cci_pending_reads_full); -`SCOPE_ASSIGN (cci_pending_writes_empty, cci_pending_writes_empty); -`SCOPE_ASSIGN (cci_pending_writes_full, cci_pending_writes_full); -`SCOPE_ASSIGN (afu_mem_req_fire, (mem_req_if.valid && mem_req_if.ready)); -`SCOPE_ASSIGN (afu_mem_req_addr, mem_req_if.addr); -`SCOPE_ASSIGN (afu_mem_rsp_fire, (mem_rsp_if.valid && mem_rsp_if.ready)); + wire mem_req_fire = mem_req_if.valid && mem_req_if.ready; + wire mem_rsp_fire = mem_rsp_if.valid && mem_rsp_if.ready; + wire avs_write_fire = avs_write[0] && ~avs_waitrequest[0]; + wire avs_read_fire = avs_read[0] && ~avs_waitrequest[0]; + wire [$bits(t_local_mem_addr)-1:0] mem_req_if_addr = mem_req_if.addr; -wire scope_changed = `SCOPE_TRIGGER; - -`RESET_RELAY (scope_reset, reset); - -VX_scope #( - .DATAW ($bits({`SCOPE_DATA_LIST,`SCOPE_UPDATE_LIST})), - .BUSW (64), - .SIZE (`SCOPE_SIZE), - .UPDW ($bits({`SCOPE_UPDATE_LIST})) -) scope ( - .clk (clk), - .reset (scope_reset), - .start (1'b0), - .stop (1'b0), - .changed (scope_changed), - .data_in ({`SCOPE_DATA_LIST,`SCOPE_UPDATE_LIST}), - .bus_in (cmd_scope_wdata), - .bus_out (cmd_scope_rdata), - .bus_read (cmd_scope_read), - .bus_write(cmd_scope_write) -); - -`else - `UNUSED_PARAM (MMIO_SCOPE_READ) - `UNUSED_PARAM (MMIO_SCOPE_WRITE) + VX_scope_tap #( + .SCOPE_ID (0), + .TRIGGERW (22), + .PROBEW ($bits({ + cmd_type, + state, + mmio_hdr.address, + mmio_hdr.length, + cp2af_sRxPort.c0.hdr.mdata, + af2cp_sTxPort.c0.hdr.address, + af2cp_sTxPort.c0.hdr.mdata, + af2cp_sTxPort.c1.hdr.address, + avs_address[0], + avs_byteenable[0], + avs_burstcount[0], + cci_mem_rd_req_ctr, + cci_mem_wr_req_ctr, + cci_rd_req_ctr, + cci_rd_rsp_ctr, + cci_wr_req_ctr, + mem_req_if_addr + })) + ) scope_tap ( + .clk(clk), + .reset(scope_reset_w[0]), + .start(1'b0), + .stop(1'b0), + .triggers({ + mem_req_fire, + mem_rsp_fire, + avs_write_fire, + avs_read_fire, + avs_waitrequest[0], + avs_readdatavalid[0], + cp2af_sRxPort.c0.mmioRdValid, + cp2af_sRxPort.c0.mmioWrValid, + cp2af_sRxPort.c0.rspValid, + cp2af_sRxPort.c1.rspValid, + af2cp_sTxPort.c0.valid, + af2cp_sTxPort.c1.valid, + cp2af_sRxPort.c0TxAlmFull, + cp2af_sRxPort.c1TxAlmFull, + af2cp_sTxPort.c2.mmioRdValid, + cci_wr_req_fire, + cci_wr_rsp_fire, + cci_rd_req_fire, + cci_rd_rsp_fire, + cci_pending_reads_full, + cci_pending_writes_empty, + cci_pending_writes_full + }), + .probes({ + cmd_type, + state, + mmio_hdr.address, + mmio_hdr.length, + cp2af_sRxPort.c0.hdr.mdata, + af2cp_sTxPort.c0.hdr.address, + af2cp_sTxPort.c0.hdr.mdata, + af2cp_sTxPort.c1.hdr.address, + avs_address[0], + avs_byteenable[0], + avs_burstcount[0], + cci_mem_rd_req_ctr, + cci_mem_wr_req_ctr, + cci_rd_req_ctr, + cci_rd_rsp_ctr, + cci_wr_req_ctr, + mem_req_if_addr + }), + .bus_in(scope_bus_in_w[0]), + .bus_out(scope_bus_out_w[0]) + ); `endif -/////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// `ifdef DBG_TRACE_AFU - always @(posedge clk) begin - for (integer i = 0; i < NUM_LOCAL_MEM_BANKS; ++i) begin - if (avs_write[i] && ~avs_waitrequest[i]) begin - `TRACE(2, ("%d: AVS Wr Req: addr=0x%0h, byteen=0x%0h, burst=0x%0h, data=0x%0h\n", $time, `TO_FULL_ADDR(avs_address[i]), avs_byteenable[i], avs_burstcount[i], avs_writedata[i])); - end - if (avs_read[i] && ~avs_waitrequest[i]) begin - `TRACE(2, ("%d: AVS Rd Req: addr=0x%0h, byteen=0x%0h, burst=0x%0h\n", $time, `TO_FULL_ADDR(avs_address[i]), avs_byteenable[i], avs_burstcount[i])); - end - if (avs_readdatavalid[i]) begin - `TRACE(2, ("%d: AVS Rd Rsp: data=0x%0h\n", $time, avs_readdata[i])); - end + always @(posedge clk) begin + for (integer i = 0; i < NUM_LOCAL_MEM_BANKS; ++i) begin + if (avs_write[i] && ~avs_waitrequest[i]) begin + `TRACE(2, ("%d: AVS Wr Req: addr=0x%0h, byteen=0x%0h, burst=0x%0h, data=0x%0h\n", $time, `TO_FULL_ADDR(avs_address[i]), avs_byteenable[i], avs_burstcount[i], avs_writedata[i])); + end + if (avs_read[i] && ~avs_waitrequest[i]) begin + `TRACE(2, ("%d: AVS Rd Req: addr=0x%0h, byteen=0x%0h, burst=0x%0h\n", $time, `TO_FULL_ADDR(avs_address[i]), avs_byteenable[i], avs_burstcount[i])); + end + if (avs_readdatavalid[i]) begin + `TRACE(2, ("%d: AVS Rd Rsp: data=0x%0h\n", $time, avs_readdata[i])); + end + end end - end `endif endmodule diff --git a/hw/rtl/core/VX_core.sv b/hw/rtl/core/VX_core.sv index b70ddccf7..251562a47 100644 --- a/hw/rtl/core/VX_core.sv +++ b/hw/rtl/core/VX_core.sv @@ -27,7 +27,7 @@ import VX_fpu_types::*; module VX_core #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_core + `SCOPE_IO_DECL // Clock input wire clk, @@ -128,10 +128,12 @@ module VX_core #( .base_dcrs (base_dcrs) ); + `SCOPE_IO_SWITCH (3) + VX_fetch #( .CORE_ID(CORE_ID) ) fetch ( - `SCOPE_BIND_VX_core_fetch + `SCOPE_IO_BIND (0) .clk (clk), .reset (fetch_reset), .base_dcrs (base_dcrs), @@ -161,7 +163,7 @@ module VX_core #( VX_issue #( .CORE_ID(CORE_ID) ) issue ( - `SCOPE_BIND_VX_core_issue + `SCOPE_IO_BIND (1) .clk (clk), .reset (issue_reset), @@ -185,7 +187,7 @@ module VX_core #( VX_execute #( .CORE_ID(CORE_ID) ) execute ( - `SCOPE_BIND_VX_core_execute + `SCOPE_IO_BIND (2) .clk (clk), .reset (execute_reset), diff --git a/hw/rtl/core/VX_execute.sv b/hw/rtl/core/VX_execute.sv index f4b132dbf..af92abd9d 100644 --- a/hw/rtl/core/VX_execute.sv +++ b/hw/rtl/core/VX_execute.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_execute #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_execute + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -120,10 +120,12 @@ module VX_execute #( .alu_commit_if (alu_commit_if) ); + `SCOPE_IO_SWITCH (2) + VX_lsu_unit #( .CORE_ID(CORE_ID) ) lsu_unit ( - `SCOPE_BIND_VX_execute_lsu_unit + `SCOPE_IO_BIND (0) .clk (clk), .reset (lsu_reset), .cache_req_if (dcache_req_if), @@ -207,7 +209,7 @@ module VX_execute #( VX_gpu_unit #( .CORE_ID(CORE_ID) ) gpu_unit ( - `SCOPE_BIND_VX_execute_gpu_unit + `SCOPE_IO_BIND (1) .clk (clk), .reset (gpu_reset), .gpu_req_if (gpu_req_if), diff --git a/hw/rtl/core/VX_fetch.sv b/hw/rtl/core/VX_fetch.sv index 14d817726..eb55e3851 100644 --- a/hw/rtl/core/VX_fetch.sv +++ b/hw/rtl/core/VX_fetch.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_fetch #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_fetch + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -40,34 +40,36 @@ module VX_fetch #( VX_ifetch_req_if ifetch_req_if(); + `SCOPE_IO_SWITCH (2) + VX_warp_sched #( .CORE_ID(CORE_ID) ) warp_sched ( - `SCOPE_BIND_VX_fetch_warp_sched + `SCOPE_IO_BIND (0) - .clk (clk), - .reset (reset), + .clk (clk), + .reset (reset), - .base_dcrs (base_dcrs), + .base_dcrs (base_dcrs), - .warp_ctl_if (warp_ctl_if), - .wrelease_if (wrelease_if), - .join_if (join_if), - .branch_ctl_if (branch_ctl_if), + .warp_ctl_if (warp_ctl_if), + .wrelease_if (wrelease_if), + .join_if (join_if), + .branch_ctl_if (branch_ctl_if), - .ifetch_req_if (ifetch_req_if), + .ifetch_req_if (ifetch_req_if), - .fetch_to_csr_if (fetch_to_csr_if), + .fetch_to_csr_if(fetch_to_csr_if), - .cmt_to_fetch_if (cmt_to_fetch_if), + .cmt_to_fetch_if(cmt_to_fetch_if), - .busy (busy) + .busy (busy) ); VX_icache_stage #( .CORE_ID(CORE_ID) ) icache_stage ( - `SCOPE_BIND_VX_fetch_icache_stage + `SCOPE_IO_BIND (1) .clk (clk), .reset (reset), diff --git a/hw/rtl/core/VX_gpu_unit.sv b/hw/rtl/core/VX_gpu_unit.sv index f7948d6b7..53344694a 100644 --- a/hw/rtl/core/VX_gpu_unit.sv +++ b/hw/rtl/core/VX_gpu_unit.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_gpu_unit #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_gpu_unit + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -354,12 +354,28 @@ module VX_gpu_unit #( assign warp_ctl_if.wid = gpu_commit_if.wid; assign {warp_ctl_if.tmc, warp_ctl_if.wspawn, warp_ctl_if.split, warp_ctl_if.barrier} = rsp_data[WCTL_DATAW-1:0]; - `SCOPE_ASSIGN (gpu_rsp_valid, warp_ctl_if.valid); - `SCOPE_ASSIGN (gpu_rsp_uuid, gpu_commit_if.uuid); - `SCOPE_ASSIGN (gpu_rsp_tmc, warp_ctl_if.tmc.valid); - `SCOPE_ASSIGN (gpu_rsp_wspawn, warp_ctl_if.wspawn.valid); - `SCOPE_ASSIGN (gpu_rsp_split, warp_ctl_if.split.valid); - `SCOPE_ASSIGN (gpu_rsp_barrier, warp_ctl_if.barrier.valid); +`ifdef SCOPE + VX_scope_tap #( + .SCOPE_ID (6), + .TRIGGERW (5), + .PROBEW (UUID_WIDTH) + ) scope_tap ( + .clk(clk), + .reset(scope_reset), + .start(1'b0), + .stop(1'b0), + .triggers({ + warp_ctl_if.valid, + warp_ctl_if.tmc.valid, + warp_ctl_if.wspawn.valid, + warp_ctl_if.split.valid, + warp_ctl_if.barrier.valid + }), + .probes({gpu_commit_if.uuid}), + .bus_in(scope_bus_in), + .bus_out(scope_bus_out) + ); +`endif // pending request diff --git a/hw/rtl/core/VX_icache_stage.sv b/hw/rtl/core/VX_icache_stage.sv index 2f82801c1..62930baf3 100644 --- a/hw/rtl/core/VX_icache_stage.sv +++ b/hw/rtl/core/VX_icache_stage.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_icache_stage #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_icache_stage + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -120,13 +120,23 @@ module VX_icache_stage #( // Can accept new response? assign icache_rsp_if.ready = ifetch_rsp_if.ready; - `SCOPE_ASSIGN (icache_req_fire, icache_req_fire); - `SCOPE_ASSIGN (icache_req_uuid, ifetch_req_if.uuid); - `SCOPE_ASSIGN (icache_req_addr, ifetch_req_if.PC); - - `SCOPE_ASSIGN (icache_rsp_fire, icache_rsp_if.valid && icache_rsp_if.ready); - `SCOPE_ASSIGN (icache_rsp_uuid, rsp_uuid); - `SCOPE_ASSIGN (icache_rsp_data, icache_rsp_if.data); +`ifdef SCOPE + wire icache_rsp_fire = icache_rsp_if.valid && icache_rsp_if.ready; + VX_scope_tap #( + .SCOPE_ID (3), + .TRIGGERW (2), + .PROBEW (UUID_WIDTH+32+UUID_WIDTH+32) + ) scope_tap ( + .clk(clk), + .reset(scope_reset), + .start(1'b0), + .stop(1'b0), + .triggers({icache_rsp_fire, icache_req_fire}), + .probes({ifetch_req_if.uuid, ifetch_req_if.PC, rsp_uuid, icache_rsp_if.data}), + .bus_in(scope_bus_in), + .bus_out(scope_bus_out) + ); +`endif `ifdef DBG_TRACE_CORE_ICACHE wire ifetch_req_fire = ifetch_req_if.valid && ifetch_req_if.ready; diff --git a/hw/rtl/core/VX_issue.sv b/hw/rtl/core/VX_issue.sv index 477315e62..847ad8d41 100644 --- a/hw/rtl/core/VX_issue.sv +++ b/hw/rtl/core/VX_issue.sv @@ -6,7 +6,7 @@ module VX_issue #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_issue + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -26,7 +26,6 @@ module VX_issue #( `endif VX_gpu_req_if.master gpu_req_if ); - VX_ibuffer_if ibuffer_if(); VX_gpr_req_if gpr_req_if(); VX_gpr_rsp_if gpr_rsp_if(); @@ -132,6 +131,8 @@ module VX_issue #( `endif .gpu_req_if (gpu_req_if) ); + + wire ibuffer_if_fire = ibuffer_if.valid && ibuffer_if.ready; reg [31:0] timeout_ctr; always @(posedge clk) begin @@ -145,7 +146,7 @@ module VX_issue #( in_use_regs[0], in_use_regs[1], in_use_regs[2], in_use_regs[3], ~dispatch_if.ready, ibuffer_if.uuid)); `endif timeout_ctr <= timeout_ctr + 1; - end else if (ibuffer_if.valid && ibuffer_if.ready) begin + end else if (ibuffer_if_fire) begin timeout_ctr <= '0; end end @@ -166,31 +167,55 @@ module VX_issue #( ); `endif - `SCOPE_ASSIGN (issue_fire, ibuffer_if.valid && ibuffer_if.ready); - `SCOPE_ASSIGN (issue_uuid, ibuffer_if.uuid); - `SCOPE_ASSIGN (issue_tmask, ibuffer_if.tmask); - `SCOPE_ASSIGN (issue_ex_type, ibuffer_if.ex_type); - `SCOPE_ASSIGN (issue_op_type, ibuffer_if.op_type); - `SCOPE_ASSIGN (issue_op_mod, ibuffer_if.op_mod); - `SCOPE_ASSIGN (issue_wb, ibuffer_if.wb); - `SCOPE_ASSIGN (issue_rd, ibuffer_if.rd); - `SCOPE_ASSIGN (issue_rs1, ibuffer_if.rs1); - `SCOPE_ASSIGN (issue_rs2, ibuffer_if.rs2); - `SCOPE_ASSIGN (issue_rs3, ibuffer_if.rs3); - `SCOPE_ASSIGN (issue_imm, ibuffer_if.imm); - `SCOPE_ASSIGN (issue_use_pc, ibuffer_if.use_PC); - `SCOPE_ASSIGN (issue_use_imm, ibuffer_if.use_imm); - `SCOPE_ASSIGN (scoreboard_delay, !scoreboard_if.ready); - `SCOPE_ASSIGN (dispatch_delay, !dispatch_if.ready); - `SCOPE_ASSIGN (gpr_rs1, gpr_rsp_if.rs1_data); - `SCOPE_ASSIGN (gpr_rs2, gpr_rsp_if.rs2_data); - `SCOPE_ASSIGN (gpr_rs3, gpr_rsp_if.rs3_data); - `SCOPE_ASSIGN (writeback_valid, writeback_if.valid); - `SCOPE_ASSIGN (writeback_uuid, writeback_if.uuid); - `SCOPE_ASSIGN (writeback_tmask, writeback_if.tmask); - `SCOPE_ASSIGN (writeback_rd, writeback_if.rd); - `SCOPE_ASSIGN (writeback_data, writeback_if.data); - `SCOPE_ASSIGN (writeback_eop, writeback_if.eop); +`ifdef SCOPE + localparam UUID_WIDTH = `UP(`UUID_BITS); + wire scoreboard_if_not_ready = ~scoreboard_if.ready; + wire dispatch_if_not_ready = ~dispatch_if.ready; + wire writeback_if_valid = writeback_if.valid; + VX_scope_tap #( + .SCOPE_ID (4), + .TRIGGERW (4), + .PROBEW (UUID_WIDTH + `NUM_THREADS + `EX_BITS + `INST_OP_BITS + `INST_MOD_BITS + + 1 + (`NR_BITS * 4) + 32 + 1 + 1 + (`NUM_THREADS * 3 * 32) + + UUID_WIDTH + `NUM_THREADS + `NR_BITS + (`NUM_THREADS*32) + 1) + ) scope_tap ( + .clk(clk), + .reset(scope_reset), + .start(1'b0), + .stop(1'b0), + .triggers({ + ibuffer_if_fire, + scoreboard_if_not_ready, + dispatch_if_not_ready, + writeback_if_valid + }), + .probes({ + ibuffer_if.uuid, + ibuffer_if.tmask, + ibuffer_if.ex_type, + ibuffer_if.op_type, + ibuffer_if.op_mod, + ibuffer_if.wb, + ibuffer_if.rd, + ibuffer_if.rs1, + ibuffer_if.rs2, + ibuffer_if.rs3, + ibuffer_if.imm, + ibuffer_if.use_PC, + ibuffer_if.use_imm, + gpr_rsp_if.rs1_data, + gpr_rsp_if.rs2_data, + gpr_rsp_if.rs3_data, + writeback_if.uuid, + writeback_if.tmask, + writeback_if.rd, + writeback_if.data, + writeback_if.eop + }), + .bus_in(scope_bus_in), + .bus_out(scope_bus_out) + ); +`endif `ifdef PERF_ENABLE reg [`PERF_CTR_BITS-1:0] perf_ibf_stalls; diff --git a/hw/rtl/core/VX_lsu_unit.sv b/hw/rtl/core/VX_lsu_unit.sv index 17841b950..adb740a10 100644 --- a/hw/rtl/core/VX_lsu_unit.sv +++ b/hw/rtl/core/VX_lsu_unit.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_lsu_unit #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_lsu_unit + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -368,16 +368,22 @@ module VX_lsu_unit #( ); `endif - // scope registration - `SCOPE_ASSIGN (dcache_req_fire, mem_req_fire); - `SCOPE_ASSIGN (dcache_req_uuid, lsu_req_if.uuid); - `SCOPE_ASSIGN (dcache_req_addr, full_addr); - `SCOPE_ASSIGN (dcache_req_rw, mem_req_rw); - `SCOPE_ASSIGN (dcache_req_byteen, mem_req_byteen); - `SCOPE_ASSIGN (dcache_req_data, mem_req_data); - `SCOPE_ASSIGN (dcache_rsp_fire, mem_rsp_fire); - `SCOPE_ASSIGN (dcache_rsp_uuid, rsp_uuid); - `SCOPE_ASSIGN (dcache_rsp_data, rsp_data); +`ifdef SCOPE + VX_scope_tap #( + .SCOPE_ID (5), + .TRIGGERW (2), + .PROBEW (UUID_WIDTH+`NUM_THREADS*(32+4+32)+1+UUID_WIDTH+`NUM_THREADS*32) + ) scope_tap ( + .clk(clk), + .reset(scope_reset), + .start(1'b0), + .stop(1'b0), + .triggers({mem_req_fire, mem_rsp_fire}), + .probes({lsu_req_if.uuid, full_addr, mem_req_rw, mem_req_byteen, mem_req_data, rsp_uuid, rsp_data}), + .bus_in(scope_bus_in), + .bus_out(scope_bus_out) + ); +`endif `ifdef DBG_TRACE_CORE_DCACHE always @(posedge clk) begin diff --git a/hw/rtl/core/VX_warp_sched.sv b/hw/rtl/core/VX_warp_sched.sv index 9c8a08c49..d44df0d38 100644 --- a/hw/rtl/core/VX_warp_sched.sv +++ b/hw/rtl/core/VX_warp_sched.sv @@ -8,7 +8,7 @@ import VX_gpu_types::*; module VX_warp_sched #( parameter CORE_ID = 0 ) ( - `SCOPE_IO_VX_warp_sched + `SCOPE_IO_DECL input wire clk, input wire reset, @@ -306,12 +306,21 @@ module VX_warp_sched #( end `RUNTIME_ASSERT(timeout_ctr < `STALL_TIMEOUT, ("%t: *** core%0d-scheduler-timeout: stalled_warps=%b", $time, CORE_ID, stalled_warps)); - `SCOPE_ASSIGN (wsched_scheduled, schedule_fire); - `SCOPE_ASSIGN (wsched_schedule_uuid, instr_uuid); - `SCOPE_ASSIGN (wsched_active_warps, active_warps); - `SCOPE_ASSIGN (wsched_stalled_warps, stalled_warps); - `SCOPE_ASSIGN (wsched_schedule_wid, schedule_wid); - `SCOPE_ASSIGN (wsched_schedule_tmask, schedule_tmask); - `SCOPE_ASSIGN (wsched_schedule_pc, schedule_pc); +`ifdef SCOPE + VX_scope_tap #( + .SCOPE_ID (2), + .TRIGGERW (1), + .PROBEW (UUID_WIDTH+`NUM_WARPS+`NUM_WARPS+NW_WIDTH+`NUM_THREADS+32) + ) scope_tap ( + .clk(clk), + .reset(scope_reset), + .start(1'b0), + .stop(1'b0), + .triggers({schedule_fire}), + .probes({instr_uuid, active_warps, stalled_warps, schedule_wid, schedule_tmask, schedule_pc}), + .bus_in(scope_bus_in), + .bus_out(scope_bus_out) + ); +`endif endmodule diff --git a/hw/rtl/libs/VX_scope.sv b/hw/rtl/libs/VX_scope.sv deleted file mode 100644 index b446155ec..000000000 --- a/hw/rtl/libs/VX_scope.sv +++ /dev/null @@ -1,244 +0,0 @@ -`include "VX_platform.vh" - -`TRACING_OFF -module VX_scope #( - parameter DATAW = 64, - parameter BUSW = 64, - parameter SIZE = 16, - parameter UPDW = 1, - parameter DELTAW = 16 -) ( - input wire clk, - input wire reset, - input wire start, - input wire stop, - input wire changed, - input wire [DATAW-1:0] data_in, - input wire [BUSW-1:0] bus_in, - output wire [BUSW-1:0] bus_out, - input wire bus_write, - input wire bus_read -); - localparam UPDW_ENABLE = (UPDW != 0); - localparam MAX_DELTA = (2 ** DELTAW) - 1; - - localparam CMD_GET_VALID = 3'd0; - localparam CMD_GET_DATA = 3'd1; - localparam CMD_GET_WIDTH = 3'd2; - localparam CMD_GET_COUNT = 3'd3; - localparam CMD_SET_START = 3'd4; - localparam CMD_SET_STOP = 3'd5; - localparam CMD_GET_OFFSET= 3'd6; - - localparam GET_VALID = 3'd0; - localparam GET_DATA = 3'd1; - localparam GET_WIDTH = 3'd2; - localparam GET_COUNT = 3'd3; - localparam GET_OFFSET = 3'd6; - - `NO_RW_RAM_CHECK reg [DATAW-1:0] data_store [SIZE-1:0]; - `NO_RW_RAM_CHECK reg [DELTAW-1:0] delta_store [SIZE-1:0]; - - reg [UPDW-1:0] prev_trigger_id; - reg [DELTAW-1:0] delta; - reg [BUSW-1:0] bus_out_r; - reg [63:0] timestamp, start_time; - - reg [`CLOG2(SIZE)-1:0] raddr, waddr, waddr_end; - - reg [`LOG2UP(DATAW)-1:0] read_offset; - - reg cmd_start, started, start_wait, recording, data_valid, read_delta, delta_flush; - - reg [BUSW-3:0] delay_val, delay_cntr; - - reg [2:0] get_cmd; - wire [2:0] cmd_type; - wire [BUSW-4:0] cmd_data; - assign {cmd_data, cmd_type} = bus_in; - - wire [UPDW-1:0] trigger_id = data_in[UPDW-1:0]; - - always @(posedge clk) begin - if (reset) begin - get_cmd <= $bits(get_cmd)'(CMD_GET_VALID); - raddr <= '0; - waddr <= '0; - waddr_end <= $bits(waddr)'(SIZE-1); - cmd_start <= 0; - started <= 0; - start_wait <= 0; - recording <= 0; - delay_val <= '0; - delay_cntr <= '0; - delta <= '0; - delta_flush <= 0; - prev_trigger_id <= '0; - read_offset <= '0; - read_delta <= '0; - data_valid <= 0; - timestamp <= '0; - start_time <= '0; - end else begin - - timestamp <= timestamp + 1; - - if (bus_write) begin - case (cmd_type) - CMD_GET_VALID, - CMD_GET_DATA, - CMD_GET_WIDTH, - CMD_GET_OFFSET, - CMD_GET_COUNT: get_cmd <= $bits(get_cmd)'(cmd_type); - CMD_SET_START: begin - delay_val <= $bits(delay_val)'(cmd_data); - cmd_start <= 1; - `ifdef DBG_TRACE_SCOPE - `TRACE(2, ("%d: *** scope: CMD_SET_START: delay_val=%0d\n", $time, $bits(delay_val)'(cmd_data))); - `endif - end - CMD_SET_STOP: begin - waddr_end <= $bits(waddr)'(cmd_data); - `ifdef DBG_TRACE_SCOPE - `TRACE(2, ("%d: *** scope: CMD_SET_STOP: waddr_end=%0d\n", $time, $bits(waddr)'(cmd_data))); - `endif - end - default:; - endcase - end - - if (!started && (start || cmd_start)) begin - started <= 1; - delta_flush <= 1; - if (0 == delay_val) begin - start_wait <= 0; - recording <= 1; - delta <= '0; - delay_cntr <= '0; - start_time <= timestamp; - `ifdef DBG_TRACE_SCOPE - `TRACE(2, ("%d: *** scope: recording start - start_time=%0d\n", $time, timestamp)); - `endif - end else begin - start_wait <= 1; - delay_cntr <= delay_val; - end - end - - if (start_wait) begin - delay_cntr <= delay_cntr - 1; - if (1 == delay_cntr) begin - start_wait <= 0; - recording <= 1; - delta <= '0; - start_time <= timestamp; - `ifdef DBG_TRACE_SCOPE - `TRACE(2, ("%d: *** scope: recording start - start_time=%0d\n", $time, timestamp)); - `endif - end - end - - if (recording) begin - if (UPDW_ENABLE != 0) begin - if (delta_flush - || changed - || (trigger_id != prev_trigger_id)) begin - delta_store[waddr] <= delta; - data_store[waddr] <= data_in; - waddr <= waddr + $bits(waddr)'(1); - delta <= '0; - delta_flush <= 0; - end else begin - delta <= delta + DELTAW'(1); - delta_flush <= (delta == (MAX_DELTA-1)); - end - prev_trigger_id <= trigger_id; - end else begin - delta_store[waddr] <= '0; - data_store[waddr] <= data_in; - waddr <= waddr + 1; - end - - if (stop - || (waddr >= waddr_end)) begin - `ifdef DBG_TRACE_SCOPE - `TRACE(2, ("%d: *** scope: recording stop - waddr=(%0d, %0d)\n", $time, waddr, waddr_end)); - `endif - waddr <= waddr; // keep last address - recording <= 0; - data_valid <= 1; - read_delta <= 1; - end - end - - if (bus_read - && (get_cmd == GET_DATA) - && data_valid) begin - if (read_delta) begin - read_delta <= '0; - end else begin - if (DATAW > BUSW) begin - if (read_offset < $bits(read_offset)'(DATAW-BUSW)) begin - read_offset <= read_offset + $bits(read_offset)'(BUSW); - end else begin - raddr <= raddr + $bits(raddr)'(1); - read_offset <= '0; - read_delta <= 1; - if (raddr == waddr) begin - data_valid <= 0; - end - end - end else begin - raddr <= raddr + 1; - read_delta <= 1; - if (raddr == waddr) begin - data_valid <= 0; - end - end - end - end - end - - if (recording) begin - if (UPDW_ENABLE != 0) begin - if (delta_flush - || changed - || (trigger_id != prev_trigger_id)) begin - delta_store[waddr] <= delta; - data_store[waddr] <= data_in; - end - end else begin - delta_store[waddr] <= '0; - data_store[waddr] <= data_in; - end - end - end - - always @(*) begin - case (get_cmd) - GET_VALID : bus_out_r = BUSW'(data_valid); - GET_WIDTH : bus_out_r = BUSW'(DATAW); - GET_COUNT : bus_out_r = BUSW'(waddr) + BUSW'(1); - GET_OFFSET: bus_out_r = BUSW'(start_time); - /* verilator lint_off WIDTH */ - GET_DATA : bus_out_r = read_delta ? BUSW'(delta_store[raddr]) : BUSW'(data_store[raddr] >> read_offset); - /* verilator lint_on WIDTH */ - default : bus_out_r = '0; - endcase - end - - assign bus_out = bus_out_r; - -`ifdef DBG_TRACE_SCOPE - always @(posedge clk) begin - if (bus_read) begin - `TRACE(2, ("%d: scope-read: cmd=%0d, addr=%0d, value=0x%0h\n", $time, get_cmd, raddr, bus_out)); - end - if (bus_write) begin - `TRACE(2, ("%d: scope-write: cmd=%0d, value=%0d\n", $time, cmd_type, cmd_data)); - end - end -`endif - -endmodule -`TRACING_ON diff --git a/hw/rtl/libs/VX_scope_switch.sv b/hw/rtl/libs/VX_scope_switch.sv new file mode 100644 index 000000000..4a5f55514 --- /dev/null +++ b/hw/rtl/libs/VX_scope_switch.sv @@ -0,0 +1,50 @@ +`include "VX_platform.vh" + +//`TRACING_OFF +module VX_scope_switch #( + parameter N = 0 +) ( + input wire clk, + input wire reset, + input wire req_in, + output wire req_out [N], + input wire rsp_in [N], + output wire rsp_out +); + if (N > 1) begin + reg req_out_r [N]; + reg rsp_out_r; + + always @(posedge clk) begin + if (reset) begin + for (integer i = 0; i < N; ++i) begin + req_out_r[i] <= 0; + end + rsp_out_r <= 0; + end else begin + for (integer i = 0; i < N; ++i) begin + req_out_r[i] <= req_in; + end + rsp_out_r <= 0; + for (integer i = 0; i < N; ++i) begin + if (rsp_in[i]) + rsp_out_r <= 1; + end + end + end + + assign req_out = req_out_r; + assign rsp_out = rsp_out_r; + + end else begin + + `UNUSED_VAR (clk) + `UNUSED_VAR (reset) + + assign req_out[0] = req_in; + assign rsp_out = rsp_in[0]; + + end + +endmodule +//`TRACING_ON diff --git a/hw/scripts/gen_config.py b/hw/scripts/gen_config.py index 2a9abf5bd..8bfc01351 100755 --- a/hw/scripts/gen_config.py +++ b/hw/scripts/gen_config.py @@ -38,8 +38,7 @@ translation_rules = [ (re.compile(r"\d+'d(\d+)"), r'\1'), (re.compile(r"\d+'b([01]+)"), r'0b\1'), (re.compile(r"128'h([\da-fA-F_]+)"), r'"\1"'), - (re.compile(r"\d+'h([\da-fA-F]+)"), r'0x\1') - + (re.compile(r"\d+'h([\da-fA-F]+)"), r'0x\1') ] with open(args.output, 'w') as f: diff --git a/hw/scripts/scope.json b/hw/scripts/scope.json deleted file mode 100644 index 2e619a193..000000000 --- a/hw/scripts/scope.json +++ /dev/null @@ -1,209 +0,0 @@ -{ - "version": 1, - "include_paths":[ - "../dpi", - "../rtl", - "../rtl/afu/opae", - "../rtl/core", - "../rtl/cache", - "../rtl/fpu_unit", - "../rtl/interfaces", - "../rtl/libs" - ], - "includes":[ - "../rtl/VX_platform.vh", - "../rtl/VX_config.vh", - "../rtl/VX_define.vh", - "../rtl/VX_gpu_types.vh", - "../rtl/fpu_unit/VX_fpu_types.vh", - "../rtl/fpu_unit/VX_fpu_define.vh", - "../rtl/cache/VX_cache_define.vh" - ], - "modules": { - "afu": { - "submodules": { - "vortex": {"type":"Vortex", "enabled":true} - } - }, - "Vortex": { - "submodules": { - "cluster": {"type":"VX_cluster", "count":"`NUM_CLUSTERS"}, - "l3cache": {"type":"VX_cache_wrap", "enabled":"`L3_ENABLED", "params":{"NUM_BANKS":"`L3_NUM_BANKS"}} - } - }, - "VX_cluster": { - "submodules": { - "socket": {"type":"VX_socket", "count":"`NUM_CORES", "enabled":true}, - "rcache": {"type":"VX_cache_wrap", "enabled":"`EXT_RASTER_ENABLED", "params":{"NUM_BANKS":"`RCACHE_NUM_BANKS"}}, - "ocache": {"type":"VX_cache_wrap", "enabled":"`EXT_ROP_ENABLED", "params":{"NUM_BANKS":"`OCACHE_NUM_BANKS"}}, - "l2cache": {"type":"VX_cache_wrap", "enabled":"`L2_ENABLED", "params":{"NUM_BANKS":"`L2_NUM_BANKS"}} - } - }, - "VX_socket": { - "submodules": { - "core": {"type":"VX_core", "count":"1", "enabled":true} - } - }, - "VX_core": { - "submodules": { - "fetch": {"type":"VX_fetch", "enabled":true}, - "decode": {"type":"VX_decode", "enabled":true}, - "issue": {"type":"VX_issue", "enabled":true}, - "execute": {"type":"VX_execute", "enabled":true}, - "commit": {"type":"VX_commit", "enabled":true} - } - }, - "VX_fetch": { - "submodules": { - "warp_sched": {"type":"VX_warp_sched"}, - "icache_stage": {"type":"VX_icache_stage"} - } - }, - "VX_warp_sched": {}, - "VX_icache_stage": {}, - "VX_decode": {}, - "VX_issue": {}, - "VX_execute": { - "submodules": { - "lsu_unit": {"type":"VX_lsu_unit"}, - "gpu_unit": {"type":"VX_gpu_unit"} - } - }, - "VX_commit": {}, - "VX_lsu_unit": {}, - "VX_gpu_unit": {}, - "VX_mem_unit": { - "submodules": { - "dcache": {"type":"VX_cache_wrap", "params":{"NUM_BANKS":"`DCACHE_NUM_BANKS"}}, - "icache": {"type":"VX_cache_wrap", "params":{"NUM_BANKS":"1"}}, - "tcache": {"type":"VX_cache_wrap", "enabled":"`EXT_TEX_ENABLED", "params":{"NUM_BANKS":"`TCACHE_NUM_BANKS"}} - } - }, - "VX_cache_wrap": { - "submodules": { - "cache": {"type":"VX_cache"} - } - }, - "VX_cache": { - "submodules": { - "bank": {"type":"VX_cache_bank", "count":"NUM_BANKS"} - } - }, - "VX_cache_bank": {} - }, - "taps": { - "afu": { - "!cmd_type":3, - "!state":3, - "?cci_sRxPort_c0_mmioRdValid":1, - "?cci_sRxPort_c0_mmioWrValid":1, - "mmio_hdr_address":16, - "mmio_hdr_length":2, - "cci_sRxPort_c0_hdr_mdata":16, - "?cci_sRxPort_c0_rspValid":1, - "?cci_sRxPort_c1_rspValid":1, - "?cci_sTxPort_c0_valid":1, - "cci_sTxPort_c0_hdr_address":42, - "cci_sTxPort_c0_hdr_mdata":16, - "?cci_sTxPort_c1_valid":1, - "cci_sTxPort_c1_hdr_address":42, - "cci_sTxPort_c2_mmioRdValid":1, - "!cci_sRxPort_c0TxAlmFull":1, - "!cci_sRxPort_c1TxAlmFull":1, - "avs_address":26, - "!avs_waitrequest":1, - "?avs_write_fire":1, - "?avs_read_fire":1, - "avs_byteenable":64, - "avs_burstcount":4, - "avs_readdatavalid":1, - "cci_mem_rd_req_ctr":26, - "cci_mem_wr_req_ctr":26, - "cci_rd_req_ctr":26, - "cci_rd_rsp_ctr":3, - "cci_wr_req_ctr":26, - "?cci_wr_req_fire":1, - "?cci_wr_rsp_fire":1, - "?cci_rd_req_fire":1, - "?cci_rd_rsp_fire":1, - "!cci_pending_reads_full":1, - "!cci_pending_writes_empty":1, - "!cci_pending_writes_full": 1, - "?afu_mem_req_fire": 1, - "afu_mem_req_addr": 26, - "?afu_mem_rsp_fire": 1 - }, - "afu/vortex": { - "!reset": 1, - "?mem_req_fire": 1, - "mem_req_addr": 32, - "mem_req_rw": 1, - "?mem_rsp_fire": 1, - "busy": 1 - }, - "afu/vortex/cluster/socket/core/fetch/warp_sched": { - "?wsched_scheduled": 1, - "wsched_schedule_uuid": "`UP(`UUID_BITS)", - "wsched_active_warps": "`NUM_WARPS", - "wsched_stalled_warps": "`NUM_WARPS", - "wsched_schedule_tmask": "`NUM_THREADS", - "wsched_schedule_wid": "`NW_BITS", - "wsched_schedule_pc": 32 - }, - "afu/vortex/cluster/socket/core/fetch/icache_stage": { - "?icache_req_fire": 1, - "icache_req_uuid": "`UP(`UUID_BITS)", - "icache_req_addr": 32, - "?icache_rsp_fire": 1, - "icache_rsp_uuid": "`UP(`UUID_BITS)", - "icache_rsp_data": 32 - }, - "afu/vortex/cluster/socket/core/issue": { - "?issue_fire": 1, - "issue_uuid": "`UP(`UUID_BITS)", - "issue_tmask":"`NUM_THREADS", - "issue_ex_type":"`EX_BITS", - "issue_op_type":"`INST_OP_BITS", - "issue_op_mod":"`INST_MOD_BITS", - "issue_wb": 1, - "issue_rd":"`NR_BITS", - "issue_rs1":"`NR_BITS", - "issue_rs2":"`NR_BITS", - "issue_rs3":"`NR_BITS", - "issue_imm": 32, - "issue_use_pc": 1, - "issue_use_imm": 1, - "gpr_rs1":"`NUM_THREADS * 32", - "gpr_rs2":"`NUM_THREADS * 32", - "gpr_rs3":"`NUM_THREADS * 32", - "?writeback_valid": 1, - "writeback_uuid": "`UP(`UUID_BITS)", - "writeback_tmask":"`NUM_THREADS", - "writeback_rd":"`NR_BITS", - "writeback_data":"`NUM_THREADS * 32", - "writeback_eop": 1, - "!scoreboard_delay": 1, - "!dispatch_delay": 1 - }, - "afu/vortex/cluster/socket/core/execute/lsu_unit": { - "?dcache_req_fire":1, - "dcache_req_uuid": "`UP(`UUID_BITS)", - "dcache_req_addr":"`NUM_THREADS * 32", - "dcache_req_rw": 1, - "dcache_req_byteen":"`NUM_THREADS * 4", - "dcache_req_data":"`NUM_THREADS * 32", - "?dcache_rsp_fire":1, - "dcache_rsp_uuid": "`UP(`UUID_BITS)", - "dcache_rsp_data":"`NUM_THREADS * 32" - }, - "afu/vortex/cluster/socket/core/execute/gpu_unit": { - "?gpu_rsp_valid": 1, - "gpu_rsp_uuid": "`UP(`UUID_BITS)", - "gpu_rsp_tmc": 1, - "gpu_rsp_wspawn": 1, - "gpu_rsp_split": 1, - "gpu_rsp_barrier": 1 - } - } - } - \ No newline at end of file diff --git a/hw/scripts/scope.py b/hw/scripts/scope.py index dd42bfc73..bd87e9b2a 100755 --- a/hw/scripts/scope.py +++ b/hw/scripts/scope.py @@ -1,827 +1,163 @@ #!/usr/bin/env python3 -import os +import sys +import argparse +import xml.etree.ElementTree as ET import re import json -import argparse -import math -vl_include_re = re.compile(r"^\s*`include\s+\"(.+)\"") -vl_define_re = re.compile(r"^\s*`define\s+(\w+)(\([\w\s,]*\))?(.*)") -vl_ifdef_re = re.compile(r"^\s*`(ifdef|ifndef|elsif)\s+(\w+)\s*$") -vl_endif_re = re.compile(r"^\s*`(endif|else)\s*$") -vl_expand_re = re.compile(r"`([0-9a-zA-Z_]+)") +vl_int_re = re.compile(r"\d+'s*h([\da-fA-F]+)") -exclude_files = [] -include_dirs = [] -macros = [] -br_stack = [] +def parse_vl_int(text): + str_hex = re.sub(vl_int_re, r'\1', text) + return int(str_hex, 16) -def translate_ternary(text): +def source_loc(xml_doc, xml_loc): + loc = xml_loc.split(",") + file_id = loc[0] + start_line = loc[1] + start_col = loc[2] + end_line = loc[3] + end_col = loc[4] + file = xml_doc.find(".//file/[@id='" + file_id + "']").get("filename") + return file + " (" + start_line + ":" + start_col + "-" + end_line + ":" + end_col + ")" - def skip_space(text, i, ln, step): - while (i >= 0) and (i < ln): - c = text[i] - if not c.isspace(): - break - i += step - return i - - def skip_expr(text, i, ln, step): - paren = 0 - checkparen = True - while (i >= 0) and (i < ln): - c = text[i] - if checkparen and (((step < 0) and (c == ')')) or ((step > 0) and (c == '('))): - paren += 1 - elif checkparen and (((step < 0) and (c == '(')) or ((step > 0) and (c == ')'))): - if (0 == paren): - break - paren -= 1 - if (0 == paren): - i = skip_space(text, i + step, ln, step) - checkparen = False - continue - elif (0 == paren) and not (c.isalnum() or (c == '_')): - break - i += step - return (i - step) - - def parse_ternary(text): - ternary = None - ln = len(text) - for i in range(1, ln): - c = text[i] - if not (c == '?'): - continue - # parse condition expression - i0 = skip_space(text, i - 1, ln, -1) - if (i < 0): - raise Exception("invalid condition expression") - i1 = skip_expr(text, i0, ln, -1) - if (i1 > i0): - raise Exception("invalid condition expression") - # parse true expression - i2 = skip_space(text, i + 1, ln, 1) - if (i2 >= ln): - raise Exception("invalid true expression") - i3 = skip_expr(text, i2, ln, 1) - if (i3 < i2): - raise Exception("invalid true expression") - # parse colon - i4 = skip_space(text, i3 + 1, ln, 1) - if (i4 >= ln): - raise Exception("invalid colon") - if not (text[i4] == ':'): - raise Exception("missing colon") - # parse false expression - i5 = skip_space(text, i4 + 1, ln, 1) - if (i5 >= ln): - raise Exception("invalid false expression") - i6 = skip_expr(text, i5, ln, 1) - if (i6 < i5): - raise Exception("invalid false expression") - ternary = (i0, i1, i2, i3, i5, i6) - break - return ternary - - while True: - pos = parse_ternary(text) - if pos is None: - break - # convert to python ternary - newText = text[:pos[1]] + text[pos[2]:pos[3]+1] + " if " + text[pos[1]:pos[0]+1] + " else " + text[pos[4]:pos[5]+1] + text[pos[5]+1:] - text = newText - - return text - -def parse_func_args(text): - args = [] - arg = '' - l = len(text) - if text[0] != '(': - raise Exception("missing leading parenthesis: " + text) - paren = 1 - for i in range(1, l): - c = text[i] - if c == '(': - paren += 1 - elif c == ')': - if paren == 0: - raise Exception("mismatched parenthesis: (" + i + ") " + text) - paren -= 1 - if paren == 0: - l = i - break - if c == ',' and paren == 1: - if arg.strip(): - args.append(arg) - arg = '' - else: - arg += c - if paren != 0: - raise Exception("missing closing parenthesis: " + text) - if arg.strip(): - args.append(arg) - - return (args, l) - -def load_include_path(dir): - if not dir in include_dirs: - print("*** include path: " + dir) - include_dirs.append(dir) - -def resolve_include_path(filename, parent_dir): - if os.path.basename(filename) in exclude_files: - return None - if os.path.isfile(filename): - return os.path.abspath(filename) - search_dirs = include_dirs - if parent_dir: - search_dirs.append(parent_dir) - for dir in search_dirs: - filepath = os.path.join(dir, filename) - if os.path.isfile(filepath): - return os.path.abspath(filepath) - raise Exception("couldn't find include file: " + filename + " in " + parent_dir) - -def remove_comments(text): - text = re.sub(re.compile("/\*.*?\*/",re.DOTALL ), "", text) # multiline - text = re.sub(re.compile("//.*?\n" ), "\n", text) # singleline - return text - -def add_macro(name, args, value): - macro = (name, args, value) - macros.append(macro) - ''' - if not args is None: - print("*** token: " + name + "(", end='') - for i in range(len(args)): - if i > 0: - print(', ', end='') - print(args[i], end='') - print(")=" + value) +def parse_dtype_width(xml_doc, dtype_id): + xml_type = xml_doc.find(".//typetable/*[@id='" + dtype_id + "']") + if xml_type.tag == "packarraydtype" or xml_type.tag == "unpackarraydtype": + sub_dtype_id = xml_type.get("sub_dtype_id") + base_width = parse_dtype_width(xml_doc, sub_dtype_id) + const = xml_type.iter("const") + left = parse_vl_int(next(const).get("name")) + right = parse_vl_int(next(const).get("name")) + return base_width * (left - right + 1) + elif xml_type.tag == "structdtype": + width = 0 + for member in xml_type.iter("memberdtype"): + sub_dtype_id = member.get("sub_dtype_id") + width = width + parse_dtype_width(xml_doc, sub_dtype_id) + return width + elif xml_type.tag == "uniondtype": + width = 0 + for member in xml_type.iter("memberdtype"): + sub_dtype_id = member.get("sub_dtype_id") + width = max(width, parse_dtype_width(xml_doc, sub_dtype_id)) + return width else: - print("*** token: " + name + "=" + value) - ''' - -def find_macro(name): - for macro in macros: - if macro[0] == name: - return macro - return None - -def expand_text(text, params): - - def re_pattern_args(args): - p = "(? 0: - p += "|" - p += arg - i += 1 - p += ")(?![0-9a-zA-Z_])" - return p - - class DoReplParam(object): - def __init__(self, params): - self.params = params - self.expanded = False - def __call__(self, match): - name = match.group(1) - self.expanded = True - return self.params[name] - - class DoReplMacro(object): - def __init__(self): - self.expanded = False - self.has_func = False - def __call__(self, match): - name = match.group(1) - macro = find_macro(name) - if macro: - if not macro[1] is None: - self.has_func = True - else: - self.expanded = True - return macro[2] - return "`" + name - - def repl_func_macro(text): - expanded = False - match = re.search(vl_expand_re, text) - if match: - name = match.group(1) - macro = find_macro(name) - if macro: - args = macro[1] - value = macro[2] - if not args is None: - str_args = text[match.end():].strip() - f_args = parse_func_args(str_args) - if len(args) == 0: - if len(f_args[0]) != 0: - raise Exception("invalid argments for macro '" + name + "': value=" + text) - else: - if len(args) != len(f_args[0]): - raise Exception("mismatch number of argments for macro '" + name + "': actual=" + len(f_args[0]) + ", expected=" + len(args)) - - pattern = re_pattern_args(args) - params = {} - for i in range(len(args)): - params[args[i]] = f_args[0][i] - dorepl = DoReplParam(params) - value = re.sub(pattern, dorepl, value) - - str_head = text[0:match.start()] - str_tail = text[match.end() + f_args[1]+1:] - text = str_head + value + str_tail - expanded = True - if expanded: - return text - return None - - changed = False - iter = 0 - - while True: - if iter > 65536: - raise Exception("Macro recursion!") - has_func = False - while True: - params_updated = False - if not params is None: - do_repl = DoReplParam(params) - pattern = re_pattern_args(params) - new_text = re.sub(pattern, do_repl, text) - if do_repl.expanded: - text = new_text - params_updated = True - do_repl = DoReplMacro() - new_text = re.sub(vl_expand_re, do_repl, text) - has_func = do_repl.has_func - if not (params_updated or do_repl.expanded): - break - text = new_text - changed = True - if not has_func: - break - expanded = repl_func_macro(text) - if not expanded: - break - text = expanded - changed = True - iter += 1 - - if changed: - return text - return None - -def parse_include(filename, nesting): - print("*** parsing: " + filename + "...") - if nesting > 99: - raise Exception("include recursion!") - #print("*** parsing '" + filename + "'...") - content = None - with open(filename, "r") as f: - content = f.read() - # remove comments - content = remove_comments(content) - # parse content - prev_line = None - for line in content.splitlines(False): - # skip empty lines - if re.match(re.compile(r'^\s*$'), line): - continue - # merge multi-line lines - if line.endswith('\\'): - if prev_line: - prev_line += line[:len(line) - 1] - else: - prev_line = line[:len(line) - 1] - continue - if prev_line: - line = prev_line + line - prev_line = None - # parse ifdef - m = re.match(vl_ifdef_re, line) - if m: - key = m.group(1) - cond = m.group(2) - taken = find_macro(cond) is not None - if key == 'ifndef': - taken = not taken - elif key == 'elsif': - br_stack.pop() - br_stack.append(taken) - #print("*** " + key + "(" + cond + ") => " + str(taken)) - continue - # parse endif - m = re.match(vl_endif_re, line) - if m: - key = m.group(1) - top = br_stack.pop() - if key == 'else': - br_stack.append(not top) - #print("*** " + key) - continue - # skip disabled blocks - if not all(br_stack): - continue + sub_dtype_id = xml_type.get("sub_dtype_id") + if sub_dtype_id != None: + return parse_dtype_width(xml_doc, sub_dtype_id) + left = xml_type.get("left") + right = xml_type.get("right") + if left != None and right != None: + return int(left) - int(right) + 1 + return 1 - # parse include - m = re.match(vl_include_re, line) - if m: - include = m.group(1) - include = resolve_include_path(include, os.path.dirname(filename)) - if include: - parse_include(include, nesting + 1) +def parse_var_name(xml_doc, xml_node): + if xml_node.tag == "varref": + return xml_node.get("name") + elif xml_node.tag == "varxref": + name = xml_node.get("name") + dotted = xml_node.get("dotted") + return dotted + '.' + name + else: + raise ET.ParseError("invalid probe entry" + source_loc(xml_doc, xml_node.get("loc"))) + return name + +def parse_sel_name(xml_doc, xml_node): + name = parse_var_name(xml_doc, xml_node.find("*")) + const = xml_node.iter("const") + offset = parse_vl_int(next(const).get("name")) + #size = parse_vl_int(next(const).get("name")) + return name + '_' + str(offset) + +def parse_array_name(xml_doc, xml_node): + if xml_node.tag == "arraysel": + name = parse_array_name(xml_doc, xml_node.find("*")) + xml_size = xml_node.find("const").get("name") + array_size = parse_vl_int(xml_size) + name = name + '_' + str(array_size) + else: + name = parse_var_name(xml_doc, xml_node) + return name + +def parse_vl_port(xml_doc, xml_node, signals): + total_width = 0 + if xml_node.tag == "concat": + for xml_child in xml_node.findall("*"): + total_width = total_width + parse_vl_port(xml_doc, xml_child, signals) + elif xml_node.tag == "varref" or xml_node.tag == "varxref": + name = parse_var_name(xml_doc, xml_node) + dtype_id = xml_node.get("dtype_id") + signal_width = parse_dtype_width(xml_doc, dtype_id) + signals.append([name, signal_width]) + total_width = total_width + signal_width + elif xml_node.tag == "sel": + name = parse_sel_name(xml_doc, xml_node) + dtype_id = xml_node.get("dtype_id") + signal_width = parse_dtype_width(xml_doc, dtype_id) + signals.append([name, signal_width]) + total_width = total_width + signal_width + elif xml_node.tag == "arraysel": + name = parse_array_name(xml_doc, xml_node) + dtype_id = xml_node.get("dtype_id") + signal_width = parse_dtype_width(xml_doc, dtype_id) + signals.append([name, signal_width]) + total_width = total_width + signal_width + else: + raise ET.ParseError("invalid probe entry: " + source_loc(xml_doc, xml_node.get("loc"))) + return total_width + +def parse_xml(filename, max_taps): + xml_doc = ET.parse(filename) + modules = {} + xml_modules = xml_doc.findall(".//module/[@origName='VX_scope_tap']") + for xml_module in xml_modules: + scope_id = parse_vl_int(xml_module.find(".//var/[@name='SCOPE_ID']/const").get("name")) + triggerw = parse_vl_int(xml_module.find(".//var/[@name='TRIGGERW']/const").get("name")) + probew = parse_vl_int(xml_module.find(".//var/[@name='PROBEW']/const").get("name")) + module_name = xml_module.get("name") + modules[module_name] = [scope_id, triggerw, probew] + + taps = [] + xml_instances = xml_doc.iter("instance") + for xml_instance in xml_instances: + if (max_taps != -1 and len(taps) >= max_taps): + break + defName = xml_instance.get("defName") + module = modules.get(defName) + if module is None: continue - # parse define - m = re.match(vl_define_re, line) - if m: - name = m.group(1) - args = m.group(2) - if args: - args = args[1:len(args)-1].strip() - if args != '': - args = args.split(',') - for i in range(len(args)): - args[i] = args[i].strip() - else: - args = [] - value = m.group(3) - add_macro(name, args, value.strip()) - continue - print("*** exiting: " + filename + "...") + triggers = [] + probes = [] + w = parse_vl_port(xml_doc, xml_instance.find(".//port/[@name='triggers']/*"), triggers) + if w != module[1]: + raise ET.ParseError("invalid triggers width: actual=" + str(w) + ", expected=" + str(module[1])) + w = parse_vl_port(xml_doc, xml_instance.find(".//port/[@name='probes']/*"), probes) + if w != module[2]: + raise ET.ParseError("invalid probes width: actual=" + str(w) + ", expected=" + str(module[2])) + signals = probes + for trigger in triggers: + signals.append(trigger) + loc = xml_instance.get("loc") + hier = xml_doc.find(".//cell/[@loc='" + loc + "']").get("hier") + path = hier.rsplit(".", 1)[0] + taps.append({"id":module[0], + "width":module[1] + module[2], + "signals":signals, + "path":path}) -def parse_includes(includes): - # change current directory to include directory - old_dir = os.getcwd() - script_dir = os.path.dirname(os.path.realpath(__file__)) - os.chdir(script_dir) - - for include in includes: - parse_include(include, 0) - load_include_path(os.path.dirname(include)) - - # restore current directory - os.chdir(old_dir) - -def load_defines(defines): - for define in defines: - key_value = define.split('=', 2) - name = key_value[0] - value = '' - if len(key_value) == 2: - value = key_value[1] - add_macro(name, None, value) - -def load_config(filename): - with open(filename, "r") as f: - config = json.load(f) - print("condfig=", config) - return config - -def eval_node(text, params): - def clog2(x): - return int(x).bit_length() - 1 - - if not type(text) == str: - return text - - expanded = expand_text(text, params) - if expanded: - text = expanded - - try: - __text = text.replace('$clog2', '__clog2') - __text = translate_ternary(__text) - __text = __text.replace('||', 'or') - __text = __text.replace('&&', 'and') - e = eval(__text, {'__clog2': clog2}) - return e - except (NameError, SyntaxError): - return text - -def gen_vl_header(file, modules, taps): - - header = ''' -`ifndef VX_SCOPE_DEFS -`define VX_SCOPE_DEFS -''' - footer = '`endif' - - def signal_size(size, mn): - if type(size) == int: - if (size != mn): - return "[" + str(size-1) + ":0]" - else: - return "" - else: - return "[" + size + "-1:0]" - - def create_signal(key, ports): - if not key in ports: - ports[key] = [] - return ports[key] - - def dic_insert(gdic, ldic, key, value, enabled): - if enabled: - ldic[key] = value - if key in gdic: - return False - if enabled: - gdic[key] = None - return True - - def trigger_name(name, size): - if type(size) == int: - if size != 1: - return "(| " + name + ")" - else: - return name - else: - return "(| " + name + ")" - - def trigger_subscripts(asize): - def Q(arr, ss, asize, idx, N): - a = asize[idx] - if (a != 0): - for i in range(a): - tmp = ss + '[' + str(i) + ']' - if (idx + 1) < N: - Q(arr, tmp, asize, idx + 1, N) - else: - arr.append(tmp) - else: - if (idx + 1) < N: - Q(arr, ss, asize, idx + 1, N) - else: - arr.append(ss) - - if asize is None: - return [""] - ln = len(asize) - if (0 == ln): - return [""] - arr = [] - Q(arr, "", asize, 0, ln) - return arr - - - def visit_path(alltaps, ports, ntype, paths, modules, taps): - curtaps = {} - - if (len(paths) != 0): - spath = paths.pop(0) - snodes = modules[ntype]["submodules"] - if not spath in snodes: - raise Exception("invalid path: " + spath + " in " + ntype) - - snode = snodes[spath] - - stype = snode["type"] - - enabled = True - if "enabled" in snode: - enabled = eval_node(snode["enabled"], None) - - subtaps = visit_path(alltaps, ports, stype, paths, modules, taps) - - scount = 0 - if "count" in snode: - scount = eval_node(snode["count"], None) - - params = None - if "params" in snode: - params = snode["params"] - - new_staps = [] - - nn = "SCOPE_IO_" + ntype - pp = create_signal(nn, ports) - - for key in subtaps: - subtap = subtaps[key] - s = subtap[0] - a = subtap[1] - t = subtap[2] - - aa = [scount] - sa = signal_size(scount, 0) - if a: - for i in a: - x = eval_node(i, params) - aa.append(x) - sa += signal_size(x, 0) - - if dic_insert(alltaps, curtaps, spath + '/' + key, (s, aa, t), enabled): - skey = key.replace('/', '_') - if enabled: - pp.append("\toutput wire" + sa + signal_size(s, 1) + " scope_" + spath + '_' + skey + ',') - new_staps.append(skey) - - ports[nn] = pp - - if (0 == scount): - nn = "SCOPE_BIND_" + ntype + '_' + spath - pp = create_signal(nn, ports) - - for st in new_staps: - if enabled: - pp.append("\t.scope_" + st + "(scope_" + spath + '_' + st + "),") - else: - pp.append("\t`UNUSED_PIN (scope_" + st + "),") - - ports[nn] = pp - else: - nn = "SCOPE_BIND_" + ntype + '_' + spath + "(__i__)" - pp = create_signal(nn, ports) - - for st in new_staps: - if enabled: - pp.append("\t.scope_" + st + "(scope_" + spath + '_' + st + "[__i__]),") - else: - pp.append("\t`UNUSED_PIN (scope_" + st + "),") - - ports[nn] = pp - else: - nn = "SCOPE_IO_" + ntype - pp = create_signal(nn, ports) - - for tk in taps: - trigger = 0 - name = tk - size = eval_node(taps[tk], None) - if name[0] == '!': - name = name[1:] - trigger = 1 - elif name[0] == '?': - name = name[1:] - trigger = 2 - if dic_insert(alltaps, curtaps, name, (size, None, trigger), True): - pp.append("\toutput wire" + signal_size(size, 1) + " scope_" + name + ',') - - ports[nn] = pp - - return curtaps - - toptaps = {} - - with open(file, 'w') as f: - - ports = {} - alltaps = {} - - for key in taps: - skey_list = key.split(',') - _taps = taps[key] - for skey in skey_list: - #print('*** processing node: ' + skey + ' ...') - paths = skey.strip().split('/') - ntype = paths.pop(0) - curtaps = visit_path(alltaps, ports, ntype, paths, modules, _taps) - for tk in curtaps: - toptaps[tk] = curtaps[tk] - - print(header, file=f) - - for key in ports: - print("`define " + key + ' \\', file=f) - for port in ports[key]: - print(port + ' \\', file=f) - print("", file=f) - - print("`define SCOPE_DECL_SIGNALS \\", file=f) - i = 0 - for key in toptaps: - tap = toptaps[key] - name = key.replace('/', '_') - size = tap[0] - asize = tap[1] - sa = "" - if asize: - for a in asize: - sa += signal_size(a, 0) - if i > 0: - print(" \\", file=f) - print('\t wire' + sa + signal_size(size, 1) + " scope_" + name + ';', file=f, end='') - i += 1 - print("", file=f) - print("", file=f) - - print("`define SCOPE_DATA_LIST \\", file=f) - i = 0 - for key in toptaps: - tap = toptaps[key] - trigger = tap[2] - if trigger != 0: - continue - name = key.replace('/', '_') - if i > 0: - print(", \\", file=f) - print("\t scope_" + name, file=f, end='') - i += 1 - print("", file=f) - print("", file=f) - - print("`define SCOPE_UPDATE_LIST \\", file=f) - i = 0 - for key in toptaps: - tap = toptaps[key] - trigger = tap[2] - if trigger == 0: - continue - name = key.replace('/', '_') - if i > 0: - print(", \\", file=f) - print("\t scope_" + name, file=f, end='') - i += 1 - print("", file=f) - print("", file=f) - - print("`define SCOPE_TRIGGER \\", file=f) - i = 0 - for key in toptaps: - tap = toptaps[key] - if tap[2] != 2: - continue - size = tap[0] - asize = tap[1] - sus = trigger_subscripts(asize) - for su in sus: - if i > 0: - print(" | \\", file=f) - print("\t(", file=f, end='') - name = trigger_name("scope_" + key.replace('/', '_') + su, size) - print(name, file=f, end='') - print(")", file=f, end='') - i += 1 - print("", file=f) - print("", file=f) - - print(footer, file=f) - - return toptaps - -def gen_cc_header(file, taps): - - header = '''#pragma once - -struct scope_module_t { - const char* name; - int index; - int parent; -}; - -struct scope_tap_t { - int width; - const char* name; - int module; -}; -''' - def flatten_path(paths, sizes): - def Q(arr, ss, idx, N, paths, sizes): - size = sizes[idx] - if size != 0: - for i in range(sizes[idx]): - tmp = ss + ('/' if (ss != '') else '') - tmp += paths[idx] + '_' + str(i) - if (idx + 1) < N: - Q(arr, tmp, idx + 1, N, paths, sizes) - else: - arr.append(tmp) - else: - tmp = ss + ('/' if (ss != '') else '') - tmp += paths[idx] - if (idx + 1) < N: - Q(arr, tmp, idx + 1, N, paths, sizes) - else: - arr.append(tmp) - - arr = [] - Q(arr, "", 0, len(asize), paths, asize) - return arr - - # flatten the taps - fdic = {} - for key in taps: - tap = taps[key] - size = str(tap[0]) - trigger = tap[2] - if (trigger != 0): - continue - paths = key.split('/') - if (len(paths) > 1): - name = paths.pop(-1) - asize = tap[1] - for ss in flatten_path(paths, asize): - fdic[ss + '/' + name ] = [size, 0] - else: - fdic[key] = [size, 0] - for key in taps: - tap = taps[key] - size = str(tap[0]) - trigger = tap[2] - if (trigger == 0): - continue - paths = key.split('/') - if (len(paths) > 1): - name = paths.pop(-1) - asize = tap[1] - for ss in flatten_path(paths, asize): - fdic[ss + '/' + name ] = [size, 0] - else: - fdic[key] = [size, 0] - - # generate module dic - mdic = {} - mdic["*"] = ("*", 0, -1) - for key in fdic: - paths = key.split('/') - if len(paths) == 1: - continue - paths.pop(-1) - parent = 0 - mk = "" - for path in paths: - mk += '/' + path - if not mk in mdic: - index = len(mdic) - mdic[mk] = (path, index, parent) - parent = index - else: - parent = mdic[mk][1] - fdic[key][1] = parent - - with open(file, 'w') as f: - print(header, file=f) - - print("static constexpr scope_module_t scope_modules[] = {", file=f) - i = 0 - for key in mdic: - m = mdic[key] - if i > 0: - print(',', file=f) - print("\t{\"" + m[0] + "\", " + str(m[1]) + ", " + str(m[2]) + "}", file=f, end='') - i += 1 - print("", file=f) - print("};", file=f) - - print("", file=f) - print("static constexpr scope_tap_t scope_taps[] = {", file=f) - i = 0 - for key in fdic: - size = fdic[key][0] - parent = fdic[key][1] - paths = key.split('/') - if len(paths) > 1: - name = paths.pop(-1) - else: - name = key - if i > 0: - print(',', file=f) - print("\t{" + size + ", \"" + name + "\", " + str(parent) + "}", file=f, end='') - i += 1 - print("", file=f) - print("};", file=f) + return {"version":"0.1.0", "taps":taps} def main(): parser = argparse.ArgumentParser(description='Scope headers generator.') - parser.add_argument('-vl', nargs='?', default='scope-defs.vh', metavar='file', help='Output Verilog header') - parser.add_argument('-cc', nargs='?', default='scope-defs.h', metavar='file', help='Output C++ header') - parser.add_argument('-D', nargs='?', action='append', metavar='macro[=value]', help='define macro') - parser.add_argument('-I', nargs='?', action='append', metavar='', help='include directory') - parser.add_argument('config', help='Json config file') + parser.add_argument('-o', nargs='?', default='scope.json', metavar='o', help='Output JSON manifest') + parser.add_argument('-n', nargs='?', default=-1, metavar='n', type=int, help='Maximum number of taps to read') + parser.add_argument('xml', help='Design XML descriptor file') args = parser.parse_args() - print("args=", args) - - global exclude_files - global include_dirs - global macros - global br_stack - - if args.D: - load_defines(args.D) - - if args.I: - for dir in args.I: - load_include_path(dir) - - config = load_config(args.config) - - exclude_files.append(os.path.basename(args.vl)) - - if "include_paths" in config: - for path in config["include_paths"]: - load_include_path(path) - - if "includes" in config: - parse_includes(config["includes"]) - - taps = gen_vl_header(args.vl, config["modules"], config["taps"]) - gen_cc_header(args.cc, taps) + #print("args=", args) + scope_taps = parse_xml(args.xml, args.n) + with open(args.o, "w") as f: + json.dump(scope_taps, f, ensure_ascii=False, indent=4) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/runtime/common/nlohmann_json.hpp b/runtime/common/nlohmann_json.hpp index 84371793f..5df7f56d7 100644 --- a/runtime/common/nlohmann_json.hpp +++ b/runtime/common/nlohmann_json.hpp @@ -4169,28 +4169,28 @@ inline std::size_t concat_length() } template -inline std::size_t concat_length(const char* cstr, Args&& ... rest); +inline std::size_t concat_length(const char* cstr, const Args& ... rest); template -inline std::size_t concat_length(const StringType& str, Args&& ... rest); +inline std::size_t concat_length(const StringType& str, const Args& ... rest); template -inline std::size_t concat_length(const char /*c*/, Args&& ... rest) +inline std::size_t concat_length(const char /*c*/, const Args& ... rest) { - return 1 + concat_length(std::forward(rest)...); + return 1 + concat_length(rest...); } template -inline std::size_t concat_length(const char* cstr, Args&& ... rest) +inline std::size_t concat_length(const char* cstr, const Args& ... rest) { // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(std::forward(rest)...); + return ::strlen(cstr) + concat_length(rest...); } template -inline std::size_t concat_length(const StringType& str, Args&& ... rest) +inline std::size_t concat_length(const StringType& str, const Args& ... rest) { - return str.size() + concat_length(std::forward(rest)...); + return str.size() + concat_length(rest...); } template @@ -4281,7 +4281,7 @@ template inline OutStringType concat(Args && ... args) { OutStringType str; - str.reserve(concat_length(std::forward(args)...)); + str.reserve(concat_length(args...)); concat_into(str, std::forward(args)...); return str; } @@ -4338,9 +4338,9 @@ class exception : public std::exception { case value_t::array: { - for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) + for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) { - if (¤t->m_parent->m_value.array->operator[](i) == current) + if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) { tokens.emplace_back(std::to_string(i)); break; @@ -4351,7 +4351,7 @@ class exception : public std::exception case value_t::object: { - for (const auto& element : *current->m_parent->m_value.object) + for (const auto& element : *current->m_parent->m_data.m_value.object) { if (&element.second == current) { @@ -5344,7 +5344,7 @@ namespace detail /* * Note all external_constructor<>::construct functions need to call - * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an * allocated value (e.g., a string). See bug issue * https://github.com/nlohmann/json/issues/2865 for more information. */ @@ -5357,9 +5357,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::boolean; - j.m_value = b; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::boolean; + j.m_data.m_value = b; j.assert_invariant(); } }; @@ -5370,18 +5370,18 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value = s; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value = s; j.assert_invariant(); } template static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value = std::move(s); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value = std::move(s); j.assert_invariant(); } @@ -5390,9 +5390,9 @@ struct external_constructor int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::string; - j.m_value.string = j.template create(str); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value.string = j.template create(str); j.assert_invariant(); } }; @@ -5403,18 +5403,18 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::binary; - j.m_value = typename BasicJsonType::binary_t(b); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::binary; + j.m_data.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); } template static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::binary; - j.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::binary; + j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); j.assert_invariant(); } }; @@ -5425,9 +5425,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_float; - j.m_value = val; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_float; + j.m_data.m_value = val; j.assert_invariant(); } }; @@ -5438,9 +5438,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_unsigned; - j.m_value = val; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_unsigned; + j.m_data.m_value = val; j.assert_invariant(); } }; @@ -5451,9 +5451,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { - j.m_value.destroy(j.m_type); - j.m_type = value_t::number_integer; - j.m_value = val; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_integer; + j.m_data.m_value = val; j.assert_invariant(); } }; @@ -5464,9 +5464,9 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = arr; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = arr; j.set_parents(); j.assert_invariant(); } @@ -5474,9 +5474,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = std::move(arr); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = std::move(arr); j.set_parents(); j.assert_invariant(); } @@ -5489,9 +5489,9 @@ struct external_constructor using std::begin; using std::end; - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value.array = j.template create(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } @@ -5499,14 +5499,14 @@ struct external_constructor template static void construct(BasicJsonType& j, const std::vector& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = value_t::array; + j.m_data.m_value.array->reserve(arr.size()); for (const bool x : arr) { - j.m_value.array->push_back(x); - j.set_parent(j.m_value.array->back()); + j.m_data.m_value.array->push_back(x); + j.set_parent(j.m_data.m_value.array->back()); } j.assert_invariant(); } @@ -5515,13 +5515,13 @@ struct external_constructor enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray& arr) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->resize(arr.size()); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = value_t::array; + j.m_data.m_value.array->resize(arr.size()); if (arr.size() > 0) { - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); } j.set_parents(); j.assert_invariant(); @@ -5534,9 +5534,9 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value = obj; + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value = obj; j.set_parents(); j.assert_invariant(); } @@ -5544,9 +5544,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value = std::move(obj); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value = std::move(obj); j.set_parents(); j.assert_invariant(); } @@ -5558,9 +5558,9 @@ struct external_constructor using std::begin; using std::end; - j.m_value.destroy(j.m_type); - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value.object = j.template create(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } @@ -6816,7 +6816,7 @@ class json_sax_dom_parser JSON_ASSERT(ref_stack.back()->is_object()); // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_value.object->operator[](val)); + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); return true; } @@ -6891,8 +6891,8 @@ class json_sax_dom_parser if (ref_stack.back()->is_array()) { - ref_stack.back()->m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_value.array->back()); + ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_data.m_value.array->back()); } JSON_ASSERT(ref_stack.back()->is_object()); @@ -7011,7 +7011,7 @@ class json_sax_dom_callback_parser // add discarded value at given key and store the reference for later if (keep && ref_stack.back()) { - object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); } return true; @@ -7096,7 +7096,7 @@ class json_sax_dom_callback_parser // remove discarded value if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) { - ref_stack.back()->m_value.array->pop_back(); + ref_stack.back()->m_data.m_value.array->pop_back(); } return true; @@ -7179,8 +7179,8 @@ class json_sax_dom_callback_parser // array if (ref_stack.back()->is_array()) { - ref_stack.back()->m_value.array->emplace_back(std::move(value)); - return {true, &(ref_stack.back()->m_value.array->back())}; + ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_data.m_value.array->back())}; } // object @@ -12891,7 +12891,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { @@ -12988,17 +12988,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_value.object->begin(); + m_it.object_iterator = m_object->m_data.m_value.object->begin(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_value.array->begin(); + m_it.array_iterator = m_object->m_data.m_value.array->begin(); break; } @@ -13032,17 +13032,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_value.object->end(); + m_it.object_iterator = m_object->m_data.m_value.object->end(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_value.array->end(); + m_it.array_iterator = m_object->m_data.m_value.array->end(); break; } @@ -13071,17 +13071,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); return m_it.object_iterator->second; } case value_t::array: { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); return *m_it.array_iterator; } @@ -13115,17 +13115,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); return &(m_it.object_iterator->second); } case value_t::array: { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); return &*m_it.array_iterator; } @@ -13168,7 +13168,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { @@ -13219,7 +13219,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: { @@ -13266,7 +13266,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: return (m_it.object_iterator == other.m_it.object_iterator); @@ -13311,7 +13311,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); @@ -13367,7 +13367,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13446,7 +13446,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13475,7 +13475,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) + switch (m_object->m_data.m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); @@ -14105,7 +14105,7 @@ class json_pointer if (reference_token == "-") { // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); + ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); } else { @@ -14157,7 +14157,7 @@ class json_pointer { // "-" always fails the range check JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_value.array->size()), + "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); } @@ -14214,7 +14214,7 @@ class json_pointer if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); + JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); } // use unchecked array access @@ -14264,7 +14264,7 @@ class json_pointer { // "-" always fails the range check JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_value.array->size()), + "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); } @@ -14459,7 +14459,7 @@ class json_pointer { case detail::value_t::array: { - if (value.m_value.array->empty()) + if (value.m_data.m_value.array->empty()) { // flatten empty array as null result[reference_string] = nullptr; @@ -14467,10 +14467,10 @@ class json_pointer else { // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) { flatten(detail::concat(reference_string, '/', std::to_string(i)), - value.m_value.array->operator[](i), result); + value.m_data.m_value.array->operator[](i), result); } } break; @@ -14478,7 +14478,7 @@ class json_pointer case detail::value_t::object: { - if (value.m_value.object->empty()) + if (value.m_data.m_value.object->empty()) { // flatten empty object as null result[reference_string] = nullptr; @@ -14486,7 +14486,7 @@ class json_pointer else { // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) + for (const auto& element : *value.m_data.m_value.object) { flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); } @@ -14533,7 +14533,7 @@ class json_pointer BasicJsonType result; // iterate the JSON object values - for (const auto& element : *value.m_value.object) + for (const auto& element : *value.m_data.m_value.object) { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { @@ -15016,7 +15016,7 @@ class binary_writer { case value_t::object: { - write_bson_object(*j.m_value.object); + write_bson_object(*j.m_data.m_value.object); break; } @@ -15051,7 +15051,7 @@ class binary_writer case value_t::boolean: { - oa->write_character(j.m_value.boolean + oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4)); break; @@ -15059,42 +15059,42 @@ class binary_writer case value_t::number_integer: { - if (j.m_value.number_integer >= 0) + if (j.m_data.m_value.number_integer >= 0) { // CBOR does not differentiate between positive signed // integers and unsigned integers. Therefore, we used the // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) + if (j.m_data.m_value.number_integer <= 0x17) { - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } } else { // The conversions below encode the sign in the first // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) + const auto positive_number = -1 - j.m_data.m_value.number_integer; + if (j.m_data.m_value.number_integer >= -24) { write_number(static_cast(0x20 + positive_number)); } @@ -15124,52 +15124,52 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_value.number_unsigned <= 0x17) + if (j.m_data.m_value.number_unsigned <= 0x17) { - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_unsigned)); + write_number(static_cast(j.m_data.m_value.number_unsigned)); } break; } case value_t::number_float: { - if (std::isnan(j.m_value.number_float)) + if (std::isnan(j.m_data.m_value.number_float)) { // NaN is 0xf97e00 in CBOR oa->write_character(to_char_type(0xF9)); oa->write_character(to_char_type(0x7E)); oa->write_character(to_char_type(0x00)); } - else if (std::isinf(j.m_value.number_float)) + else if (std::isinf(j.m_data.m_value.number_float)) { // Infinity is 0xf97c00, -Infinity is 0xf9fc00 oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); oa->write_character(to_char_type(0x00)); } else { - write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); + write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); } break; } @@ -15177,7 +15177,7 @@ class binary_writer case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); + const auto N = j.m_data.m_value.string->size(); if (N <= 0x17) { write_number(static_cast(0x60 + N)); @@ -15207,15 +15207,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); + reinterpret_cast(j.m_data.m_value.string->c_str()), + j.m_data.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); + const auto N = j.m_data.m_value.array->size(); if (N <= 0x17) { write_number(static_cast(0x80 + N)); @@ -15244,7 +15244,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_value.array) + for (const auto& el : *j.m_data.m_value.array) { write_cbor(el); } @@ -15253,32 +15253,32 @@ class binary_writer case value_t::binary: { - if (j.m_value.binary->has_subtype()) + if (j.m_data.m_value.binary->has_subtype()) { - if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd8)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd9)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xda)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } - else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xdb)); - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } } // step 1: write control byte and the binary array size - const auto N = j.m_value.binary->size(); + const auto N = j.m_data.m_value.binary->size(); if (N <= 0x17) { write_number(static_cast(0x40 + N)); @@ -15308,7 +15308,7 @@ class binary_writer // step 2: write each element oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), + reinterpret_cast(j.m_data.m_value.binary->data()), N); break; @@ -15317,7 +15317,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); + const auto N = j.m_data.m_value.object->size(); if (N <= 0x17) { write_number(static_cast(0xA0 + N)); @@ -15346,7 +15346,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_value.object) + for (const auto& el : *j.m_data.m_value.object) { write_cbor(el.first); write_cbor(el.second); @@ -15375,7 +15375,7 @@ class binary_writer case value_t::boolean: // true and false { - oa->write_character(j.m_value.boolean + oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2)); break; @@ -15383,75 +15383,75 @@ class binary_writer case value_t::number_integer: { - if (j.m_value.number_integer >= 0) + if (j.m_data.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive // signed integers and unsigned integers. Therefore, we used // the code from the value_t::number_unsigned case here. - if (j.m_value.number_unsigned < 128) + if (j.m_data.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } } else { - if (j.m_value.number_integer >= -32) + if (j.m_data.m_value.number_integer >= -32) { // negative fixnum - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } } break; @@ -15459,48 +15459,48 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_value.number_unsigned < 128) + if (j.m_data.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); + write_number(static_cast(j.m_data.m_value.number_integer)); } break; } case value_t::number_float: { - write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); + write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); break; } case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); + const auto N = j.m_data.m_value.string->size(); if (N <= 31) { // fixstr @@ -15527,15 +15527,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); + reinterpret_cast(j.m_data.m_value.string->c_str()), + j.m_data.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); + const auto N = j.m_data.m_value.array->size(); if (N <= 15) { // fixarray @@ -15555,7 +15555,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_value.array) + for (const auto& el : *j.m_data.m_value.array) { write_msgpack(el); } @@ -15566,10 +15566,10 @@ class binary_writer { // step 0: determine if the binary type has a set subtype to // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_value.binary->has_subtype(); + const bool use_ext = j.m_data.m_value.binary->has_subtype(); // step 1: write control byte and the byte string length - const auto N = j.m_value.binary->size(); + const auto N = j.m_data.m_value.binary->size(); if (N <= (std::numeric_limits::max)()) { std::uint8_t output_type{}; @@ -15634,12 +15634,12 @@ class binary_writer // step 1.5: if this is an ext type, write the subtype if (use_ext) { - write_number(static_cast(j.m_value.binary->subtype())); + write_number(static_cast(j.m_data.m_value.binary->subtype())); } // step 2: write the byte string oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), + reinterpret_cast(j.m_data.m_value.binary->data()), N); break; @@ -15648,7 +15648,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); + const auto N = j.m_data.m_value.object->size(); if (N <= 15) { // fixmap @@ -15668,7 +15668,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_value.object) + for (const auto& el : *j.m_data.m_value.object) { write_msgpack(el.first); write_msgpack(el.second); @@ -15708,7 +15708,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(j.m_value.boolean + oa->write_character(j.m_data.m_value.boolean ? to_char_type('T') : to_char_type('F')); } @@ -15717,19 +15717,19 @@ class binary_writer case value_t::number_integer: { - write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); break; } case value_t::number_unsigned: { - write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); break; } case value_t::number_float: { - write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); break; } @@ -15739,10 +15739,10 @@ class binary_writer { oa->write_character(to_char_type('S')); } - write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); + reinterpret_cast(j.m_data.m_value.string->c_str()), + j.m_data.m_value.string->size()); break; } @@ -15754,7 +15754,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_value.array->empty()) + if (use_type && !j.m_data.m_value.array->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15777,10 +15777,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); } - for (const auto& el : *j.m_value.array) + for (const auto& el : *j.m_data.m_value.array) { write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); } @@ -15800,7 +15800,7 @@ class binary_writer oa->write_character(to_char_type('[')); } - if (use_type && !j.m_value.binary->empty()) + if (use_type && !j.m_data.m_value.binary->empty()) { JSON_ASSERT(use_count); oa->write_character(to_char_type('$')); @@ -15810,21 +15810,21 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); } if (use_type) { oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - j.m_value.binary->size()); + reinterpret_cast(j.m_data.m_value.binary->data()), + j.m_data.m_value.binary->size()); } else { - for (size_t i = 0; i < j.m_value.binary->size(); ++i) + for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) { oa->write_character(to_char_type('U')); - oa->write_character(j.m_value.binary->data()[i]); + oa->write_character(j.m_data.m_value.binary->data()[i]); } } @@ -15838,9 +15838,9 @@ class binary_writer case value_t::object: { - if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end()) + if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) { - if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) + if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) { break; } @@ -15852,7 +15852,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_value.object->empty()) + if (use_type && !j.m_data.m_value.object->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15875,10 +15875,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); } - for (const auto& el : *j.m_value.object) + for (const auto& el : *j.m_data.m_value.object) { write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); oa->write_characters( @@ -16028,19 +16028,19 @@ class binary_writer void write_bson_unsigned(const string_t& name, const BasicJsonType& j) { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(j.m_value.number_unsigned), true); + write_number(static_cast(j.m_data.m_value.number_unsigned), true); } - else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + else if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(j.m_value.number_unsigned), true); + write_number(static_cast(j.m_data.m_value.number_unsigned), true); } else { - JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); + JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); } } @@ -16121,13 +16121,13 @@ class binary_writer switch (j.type()) { case value_t::object: - return header_size + calc_bson_object_size(*j.m_value.object); + return header_size + calc_bson_object_size(*j.m_data.m_value.object); case value_t::array: - return header_size + calc_bson_array_size(*j.m_value.array); + return header_size + calc_bson_array_size(*j.m_data.m_value.array); case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_value.binary); + return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); case value_t::boolean: return header_size + 1ul; @@ -16136,13 +16136,13 @@ class binary_writer return header_size + 8ul; case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_value.number_integer); + return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); + return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); case value_t::string: - return header_size + calc_bson_string_size(*j.m_value.string); + return header_size + calc_bson_string_size(*j.m_data.m_value.string); case value_t::null: return header_size + 0ul; @@ -16168,28 +16168,28 @@ class binary_writer switch (j.type()) { case value_t::object: - return write_bson_object_entry(name, *j.m_value.object); + return write_bson_object_entry(name, *j.m_data.m_value.object); case value_t::array: - return write_bson_array(name, *j.m_value.array); + return write_bson_array(name, *j.m_data.m_value.array); case value_t::binary: - return write_bson_binary(name, *j.m_value.binary); + return write_bson_binary(name, *j.m_data.m_value.binary); case value_t::boolean: - return write_bson_boolean(name, j.m_value.boolean); + return write_bson_boolean(name, j.m_data.m_value.boolean); case value_t::number_float: - return write_bson_double(name, j.m_value.number_float); + return write_bson_double(name, j.m_data.m_value.number_float); case value_t::number_integer: - return write_bson_integer(name, j.m_value.number_integer); + return write_bson_integer(name, j.m_data.m_value.number_integer); case value_t::number_unsigned: return write_bson_unsigned(name, j); case value_t::string: - return write_bson_string(name, *j.m_value.string); + return write_bson_string(name, *j.m_data.m_value.string); case value_t::null: return write_bson_null(name); @@ -16462,35 +16462,35 @@ class binary_writer return 'Z'; case value_t::boolean: - return j.m_value.boolean ? 'T' : 'F'; + return j.m_data.m_value.boolean ? 'T' : 'F'; case value_t::number_integer: { - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'i'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'U'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'I'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) { return 'u'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'l'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) { return 'm'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) { return 'L'; } @@ -16500,35 +16500,35 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'i'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'U'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'I'; } - if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'u'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'l'; } - if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'm'; } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'L'; } - if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits::max)()) + if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) { return 'M'; } @@ -16537,7 +16537,7 @@ class binary_writer } case value_t::number_float: - return get_ubjson_float_prefix(j.m_value.number_float); + return get_ubjson_float_prefix(j.m_data.m_value.number_float); case value_t::string: return 'S'; @@ -16586,7 +16586,7 @@ class binary_writer std::size_t len = (value.at(key).empty() ? 0 : 1); for (const auto& el : value.at(key)) { - len *= static_cast(el.m_value.number_unsigned); + len *= static_cast(el.m_data.m_value.number_unsigned); } key = "_ArrayData_"; @@ -16608,70 +16608,70 @@ class binary_writer { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'i') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'u') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'I') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'm') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'l') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'M') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_unsigned), true); + write_number(static_cast(el.m_data.m_value.number_unsigned), true); } } else if (dtype == 'L') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_integer), true); + write_number(static_cast(el.m_data.m_value.number_integer), true); } } else if (dtype == 'd') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_float), true); + write_number(static_cast(el.m_data.m_value.number_float), true); } } else if (dtype == 'D') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_value.number_float), true); + write_number(static_cast(el.m_data.m_value.number_float), true); } } return false; @@ -18032,11 +18032,11 @@ class serializer const unsigned int indent_step, const unsigned int current_indent = 0) { - switch (val.m_type) + switch (val.m_data.m_type) { case value_t::object: { - if (val.m_value.object->empty()) + if (val.m_data.m_value.object->empty()) { o->write_characters("{}", 2); return; @@ -18054,8 +18054,8 @@ class serializer } // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + auto i = val.m_data.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) { o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); @@ -18066,8 +18066,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + JSON_ASSERT(i != val.m_data.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -18083,8 +18083,8 @@ class serializer o->write_character('{'); // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + auto i = val.m_data.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) { o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -18094,8 +18094,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + JSON_ASSERT(i != val.m_data.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); o->write_characters("\":", 2); @@ -18109,7 +18109,7 @@ class serializer case value_t::array: { - if (val.m_value.array->empty()) + if (val.m_data.m_value.array->empty()) { o->write_characters("[]", 2); return; @@ -18127,8 +18127,8 @@ class serializer } // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) + for (auto i = val.m_data.m_value.array->cbegin(); + i != val.m_data.m_value.array->cend() - 1; ++i) { o->write_characters(indent_string.c_str(), new_indent); dump(*i, true, ensure_ascii, indent_step, new_indent); @@ -18136,9 +18136,9 @@ class serializer } // last element - JSON_ASSERT(!val.m_value.array->empty()); + JSON_ASSERT(!val.m_data.m_value.array->empty()); o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -18149,16 +18149,16 @@ class serializer o->write_character('['); // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) + for (auto i = val.m_data.m_value.array->cbegin(); + i != val.m_data.m_value.array->cend() - 1; ++i) { dump(*i, false, ensure_ascii, indent_step, current_indent); o->write_character(','); } // last element - JSON_ASSERT(!val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + JSON_ASSERT(!val.m_data.m_value.array->empty()); + dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); o->write_character(']'); } @@ -18169,7 +18169,7 @@ class serializer case value_t::string: { o->write_character('\"'); - dump_escaped(*val.m_value.string, ensure_ascii); + dump_escaped(*val.m_data.m_value.string, ensure_ascii); o->write_character('\"'); return; } @@ -18191,24 +18191,24 @@ class serializer o->write_characters("\"bytes\": [", 10); - if (!val.m_value.binary->empty()) + if (!val.m_data.m_value.binary->empty()) { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_data.m_value.binary->cbegin(); + i != val.m_data.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_characters(", ", 2); } - dump_integer(val.m_value.binary->back()); + dump_integer(val.m_data.m_value.binary->back()); } o->write_characters("],\n", 3); o->write_characters(indent_string.c_str(), new_indent); o->write_characters("\"subtype\": ", 11); - if (val.m_value.binary->has_subtype()) + if (val.m_data.m_value.binary->has_subtype()) { - dump_integer(val.m_value.binary->subtype()); + dump_integer(val.m_data.m_value.binary->subtype()); } else { @@ -18222,21 +18222,21 @@ class serializer { o->write_characters("{\"bytes\":[", 10); - if (!val.m_value.binary->empty()) + if (!val.m_data.m_value.binary->empty()) { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_data.m_value.binary->cbegin(); + i != val.m_data.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_character(','); } - dump_integer(val.m_value.binary->back()); + dump_integer(val.m_data.m_value.binary->back()); } o->write_characters("],\"subtype\":", 12); - if (val.m_value.binary->has_subtype()) + if (val.m_data.m_value.binary->has_subtype()) { - dump_integer(val.m_value.binary->subtype()); + dump_integer(val.m_data.m_value.binary->subtype()); o->write_character('}'); } else @@ -18249,7 +18249,7 @@ class serializer case value_t::boolean: { - if (val.m_value.boolean) + if (val.m_data.m_value.boolean) { o->write_characters("true", 4); } @@ -18262,19 +18262,19 @@ class serializer case value_t::number_integer: { - dump_integer(val.m_value.number_integer); + dump_integer(val.m_data.m_value.number_integer); return; } case value_t::number_unsigned: { - dump_integer(val.m_value.number_unsigned); + dump_integer(val.m_data.m_value.number_unsigned); return; } case value_t::number_float: { - dump_float(val.m_value.number_float); + dump_float(val.m_data.m_value.number_float); return; } @@ -18849,7 +18849,7 @@ class serializer : (0xFFu >> type) & (byte); const std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < 400); + JSON_ASSERT(index < utf8d.size()); state = utf8d[index]; return state; } @@ -19771,6 +19771,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void destroy(value_t t) { + if ( + (t == value_t::object && object == nullptr) || + (t == value_t::array && array == nullptr) || + (t == value_t::string && string == nullptr) || + (t == value_t::binary && binary == nullptr) + ) + { + //not initialized (e.g. due to exception in the ctor) + return; + } if (t == value_t::array || t == value_t::object) { // flatten the current json_value to a heap-allocated stack @@ -19801,18 +19811,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // its children to the stack to be processed later if (current_item.is_array()) { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); - current_item.m_value.array->clear(); + current_item.m_data.m_value.array->clear(); } else if (current_item.is_object()) { - for (auto&& it : *current_item.m_value.object) + for (auto&& it : *current_item.m_data.m_value.object) { stack.push_back(std::move(it.second)); } - current_item.m_value.object->clear(); + current_item.m_data.m_value.object->clear(); } // it's now safe that current_item get destructed @@ -19889,10 +19899,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec */ void assert_invariant(bool check_parents = true) const noexcept { - JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); - JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); - JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); - JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); + JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); + JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); + JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); + JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); #if JSON_DIAGNOSTICS JSON_TRY @@ -19911,11 +19921,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void set_parents() { #if JSON_DIAGNOSTICS - switch (m_type) + switch (m_data.m_type) { case value_t::array: { - for (auto& element : *m_value.array) + for (auto& element : *m_data.m_value.array) { element.m_parent = this; } @@ -19924,7 +19934,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::object: { - for (auto& element : *m_value.object) + for (auto& element : *m_data.m_value.object) { element.second.m_parent = this; } @@ -19965,7 +19975,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); - if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -20021,7 +20031,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief create an empty value with a given type /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const value_t v) - : m_type(v), m_value(v) + : m_data(v) { assert_invariant(); } @@ -20095,12 +20105,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec *this = nullptr; break; case value_t::discarded: - m_type = value_t::discarded; + m_data.m_type = value_t::discarded; break; default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } - JSON_ASSERT(m_type == val.type()); + JSON_ASSERT(m_data.m_type == val.type()); set_parents(); assert_invariant(); } @@ -20138,22 +20148,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_an_object) { // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; + m_data.m_type = value_t::object; + m_data.m_value = value_t::object; for (auto& element_ref : init) { auto element = element_ref.moved_or_copied(); - m_value.object->emplace( - std::move(*((*element.m_value.array)[0].m_value.string)), - std::move((*element.m_value.array)[1])); + m_data.m_value.object->emplace( + std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), + std::move((*element.m_data.m_value.array)[1])); } } else { // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init.begin(), init.end()); + m_data.m_type = value_t::array; + m_data.m_value.array = create(init.begin(), init.end()); } set_parents(); @@ -20166,8 +20176,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = init; + res.m_data.m_type = value_t::binary; + res.m_data.m_value = init; return res; } @@ -20177,8 +20187,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(init, subtype); + res.m_data.m_type = value_t::binary; + res.m_data.m_value = binary_t(init, subtype); return res; } @@ -20188,8 +20198,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = std::move(init); + res.m_data.m_type = value_t::binary; + res.m_data.m_value = std::move(init); return res; } @@ -20199,8 +20209,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(std::move(init), subtype); + res.m_data.m_type = value_t::binary; + res.m_data.m_value = binary_t(std::move(init), subtype); return res; } @@ -20222,10 +20232,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief construct an array with count copies of given value /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) + basic_json(size_type cnt, const basic_json& val): + m_data{cnt, val} { - m_value.array = create(cnt, val); set_parents(); assert_invariant(); } @@ -20247,10 +20256,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // copy type from first iterator - m_type = first.m_object->m_type; + m_data.m_type = first.m_object->m_data.m_type; // check if iterator range is complete for primitive values - switch (m_type) + switch (m_data.m_type) { case value_t::boolean: case value_t::number_float: @@ -20275,55 +20284,55 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } - switch (m_type) + switch (m_data.m_type) { case value_t::number_integer: { - m_value.number_integer = first.m_object->m_value.number_integer; + m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; break; } case value_t::number_unsigned: { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; + m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; break; } case value_t::number_float: { - m_value.number_float = first.m_object->m_value.number_float; + m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; break; } case value_t::boolean: { - m_value.boolean = first.m_object->m_value.boolean; + m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; break; } case value_t::string: { - m_value = *first.m_object->m_value.string; + m_data.m_value = *first.m_object->m_data.m_value.string; break; } case value_t::object: { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); + m_data.m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); + m_data.m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); break; } case value_t::binary: { - m_value = *first.m_object->m_value.binary; + m_data.m_value = *first.m_object->m_data.m_value.binary; break; } @@ -20350,59 +20359,59 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief copy constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const basic_json& other) - : json_base_class_t(other), - m_type(other.m_type) + : json_base_class_t(other) { + m_data.m_type = other.m_data.m_type; // check of passed value is valid other.assert_invariant(); - switch (m_type) + switch (m_data.m_type) { case value_t::object: { - m_value = *other.m_value.object; + m_data.m_value = *other.m_data.m_value.object; break; } case value_t::array: { - m_value = *other.m_value.array; + m_data.m_value = *other.m_data.m_value.array; break; } case value_t::string: { - m_value = *other.m_value.string; + m_data.m_value = *other.m_data.m_value.string; break; } case value_t::boolean: { - m_value = other.m_value.boolean; + m_data.m_value = other.m_data.m_value.boolean; break; } case value_t::number_integer: { - m_value = other.m_value.number_integer; + m_data.m_value = other.m_data.m_value.number_integer; break; } case value_t::number_unsigned: { - m_value = other.m_value.number_unsigned; + m_data.m_value = other.m_data.m_value.number_unsigned; break; } case value_t::number_float: { - m_value = other.m_value.number_float; + m_data.m_value = other.m_data.m_value.number_float; break; } case value_t::binary: { - m_value = *other.m_value.binary; + m_data.m_value = *other.m_data.m_value.binary; break; } @@ -20420,15 +20429,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(basic_json&& other) noexcept : json_base_class_t(std::move(other)), - m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) + m_data(std::move(other.m_data)) { // check that passed value is valid other.assert_invariant(false); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; + other.m_data.m_type = value_t::null; + other.m_data.m_value = {}; set_parents(); assert_invariant(); @@ -20448,8 +20456,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec other.assert_invariant(); using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); + swap(m_data.m_type, other.m_data.m_type); + swap(m_data.m_value, other.m_data.m_value); json_base_class_t::operator=(std::move(other)); set_parents(); @@ -20462,7 +20470,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec ~basic_json() noexcept { assert_invariant(false); - m_value.destroy(m_type); } /// @} @@ -20502,7 +20509,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/type/ constexpr value_t type() const noexcept { - return m_type; + return m_data.m_type; } /// @brief return whether type is primitive @@ -20523,14 +20530,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_null/ constexpr bool is_null() const noexcept { - return m_type == value_t::null; + return m_data.m_type == value_t::null; } /// @brief return whether value is a boolean /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ constexpr bool is_boolean() const noexcept { - return m_type == value_t::boolean; + return m_data.m_type == value_t::boolean; } /// @brief return whether value is a number @@ -20544,63 +20551,63 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ constexpr bool is_number_integer() const noexcept { - return m_type == value_t::number_integer || m_type == value_t::number_unsigned; + return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; } /// @brief return whether value is an unsigned integer number /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ constexpr bool is_number_unsigned() const noexcept { - return m_type == value_t::number_unsigned; + return m_data.m_type == value_t::number_unsigned; } /// @brief return whether value is a floating-point number /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ constexpr bool is_number_float() const noexcept { - return m_type == value_t::number_float; + return m_data.m_type == value_t::number_float; } /// @brief return whether value is an object /// @sa https://json.nlohmann.me/api/basic_json/is_object/ constexpr bool is_object() const noexcept { - return m_type == value_t::object; + return m_data.m_type == value_t::object; } /// @brief return whether value is an array /// @sa https://json.nlohmann.me/api/basic_json/is_array/ constexpr bool is_array() const noexcept { - return m_type == value_t::array; + return m_data.m_type == value_t::array; } /// @brief return whether value is a string /// @sa https://json.nlohmann.me/api/basic_json/is_string/ constexpr bool is_string() const noexcept { - return m_type == value_t::string; + return m_data.m_type == value_t::string; } /// @brief return whether value is a binary array /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ constexpr bool is_binary() const noexcept { - return m_type == value_t::binary; + return m_data.m_type == value_t::binary; } /// @brief return whether value is discarded /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ constexpr bool is_discarded() const noexcept { - return m_type == value_t::discarded; + return m_data.m_type == value_t::discarded; } /// @brief return the type of the JSON value (implicit) /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ constexpr operator value_t() const noexcept { - return m_type; + return m_data.m_type; } /// @} @@ -20615,7 +20622,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (JSON_HEDLEY_LIKELY(is_boolean())) { - return m_value.boolean; + return m_data.m_value.boolean; } JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); @@ -20624,97 +20631,97 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { - return is_object() ? m_value.object : nullptr; + return is_object() ? m_data.m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { - return is_object() ? m_value.object : nullptr; + return is_object() ? m_data.m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { - return is_array() ? m_value.array : nullptr; + return is_array() ? m_data.m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { - return is_array() ? m_value.array : nullptr; + return is_array() ? m_data.m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { - return is_string() ? m_value.string : nullptr; + return is_string() ? m_data.m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { - return is_string() ? m_value.string : nullptr; + return is_string() ? m_data.m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { - return is_boolean() ? &m_value.boolean : nullptr; + return is_boolean() ? &m_data.m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { - return is_boolean() ? &m_value.boolean : nullptr; + return is_boolean() ? &m_data.m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_integer() ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_integer() ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { - return is_number_float() ? &m_value.number_float : nullptr; + return is_number_float() ? &m_data.m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { - return is_number_float() ? &m_value.number_float : nullptr; + return is_number_float() ? &m_data.m_value.number_float : nullptr; } /// get a pointer to the value (binary) binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept { - return is_binary() ? m_value.binary : nullptr; + return is_binary() ? m_data.m_value.binary : nullptr; } /// get a pointer to the value (binary) constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept { - return is_binary() ? m_value.binary : nullptr; + return is_binary() ? m_data.m_value.binary : nullptr; } /*! @@ -21152,7 +21159,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return set_parent(m_value.array->at(idx)); + return set_parent(m_data.m_value.array->at(idx)); } JSON_CATCH (std::out_of_range&) { @@ -21175,7 +21182,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return m_value.array->at(idx); + return m_data.m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { @@ -21199,8 +21206,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(key); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(key); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -21219,8 +21226,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(std::forward(key)); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(std::forward(key)); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -21237,8 +21244,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(key); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(key); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -21257,8 +21264,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_value.object->find(std::forward(key)); - if (it == m_value.object->end()) + auto it = m_data.m_value.object->find(std::forward(key)); + if (it == m_data.m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -21272,8 +21279,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty array if (is_null()) { - m_type = value_t::array; - m_value.array = create(); + m_data.m_type = value_t::array; + m_data.m_value.array = create(); assert_invariant(); } @@ -21281,17 +21288,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_array())) { // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) + if (idx >= m_data.m_value.array->size()) { #if JSON_DIAGNOSTICS // remember array size & capacity before resizing - const auto old_size = m_value.array->size(); - const auto old_capacity = m_value.array->capacity(); + const auto old_size = m_data.m_value.array->size(); + const auto old_capacity = m_data.m_value.array->capacity(); #endif - m_value.array->resize(idx + 1); + m_data.m_value.array->resize(idx + 1); #if JSON_DIAGNOSTICS - if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -21305,7 +21312,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec assert_invariant(); } - return m_value.array->operator[](idx); + return m_data.m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -21318,7 +21325,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { - return m_value.array->operator[](idx); + return m_data.m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -21331,15 +21338,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_type = value_t::object; - m_value.object = create(); + m_data.m_type = value_t::object; + m_data.m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_value.object->emplace(std::move(key), nullptr); + auto result = m_data.m_value.object->emplace(std::move(key), nullptr); return set_parent(result.first->second); } @@ -21353,8 +21360,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_value.object->find(key); - JSON_ASSERT(it != m_value.object->end()); + auto it = m_data.m_value.object->find(key); + JSON_ASSERT(it != m_data.m_value.object->end()); return it->second; } @@ -21384,15 +21391,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_type = value_t::object; - m_value.object = create(); + m_data.m_type = value_t::object; + m_data.m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_value.object->emplace(std::forward(key), nullptr); + auto result = m_data.m_value.object->emplace(std::forward(key), nullptr); return set_parent(result.first->second); } @@ -21408,8 +21415,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_value.object->find(std::forward(key)); - JSON_ASSERT(it != m_value.object->end()); + auto it = m_data.m_value.object->find(std::forward(key)); + JSON_ASSERT(it != m_data.m_value.object->end()); return it->second; } @@ -21646,7 +21653,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_type) + switch (m_data.m_type) { case value_t::boolean: case value_t::number_float: @@ -21663,32 +21670,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.string); + std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); + m_data.m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.binary); + std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); + m_data.m_value.binary = nullptr; } - m_type = value_t::null; + m_data.m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); break; } @@ -21716,7 +21723,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_type) + switch (m_data.m_type) { case value_t::boolean: case value_t::number_float: @@ -21734,33 +21741,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.string); + std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); + m_data.m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_data.m_value.binary); + std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); + m_data.m_value.binary = nullptr; } - m_type = value_t::null; + m_data.m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; } @@ -21785,7 +21792,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - return m_value.object->erase(std::forward(key)); + return m_data.m_value.object->erase(std::forward(key)); } template < typename KeyType, detail::enable_if_t < @@ -21798,10 +21805,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - const auto it = m_value.object->find(std::forward(key)); - if (it != m_value.object->end()) + const auto it = m_data.m_value.object->find(std::forward(key)); + if (it != m_data.m_value.object->end()) { - m_value.object->erase(it); + m_data.m_value.object->erase(it); return 1; } return 0; @@ -21839,7 +21846,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); } - m_value.array->erase(m_value.array->begin() + static_cast(idx)); + m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast(idx)); } else { @@ -21865,7 +21872,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(key); + result.m_it.object_iterator = m_data.m_value.object->find(key); } return result; @@ -21879,7 +21886,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(key); + result.m_it.object_iterator = m_data.m_value.object->find(key); } return result; @@ -21895,7 +21902,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); } return result; @@ -21911,7 +21918,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); } return result; @@ -21922,7 +21929,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(const typename object_t::key_type& key) const { // return 0 for all nonobject types - return is_object() ? m_value.object->count(key) : 0; + return is_object() ? m_data.m_value.object->count(key) : 0; } /// @brief returns the number of occurrences of a key in a JSON object @@ -21932,14 +21939,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(KeyType && key) const { // return 0 for all nonobject types - return is_object() ? m_value.object->count(std::forward(key)) : 0; + return is_object() ? m_data.m_value.object->count(std::forward(key)) : 0; } /// @brief check the existence of an element in a JSON object /// @sa https://json.nlohmann.me/api/basic_json/contains/ bool contains(const typename object_t::key_type& key) const { - return is_object() && m_value.object->find(key) != m_value.object->end(); + return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); } /// @brief check the existence of an element in a JSON object @@ -21948,7 +21955,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::is_usable_as_basic_json_key_type::value, int> = 0> bool contains(KeyType && key) const { - return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); + return is_object() && m_data.m_value.object->find(std::forward(key)) != m_data.m_value.object->end(); } /// @brief check the existence of an element in a JSON object given a JSON pointer @@ -22118,7 +22125,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/empty/ bool empty() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::null: { @@ -22129,13 +22136,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::empty() - return m_value.array->empty(); + return m_data.m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() - return m_value.object->empty(); + return m_data.m_value.object->empty(); } case value_t::string: @@ -22157,7 +22164,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/size/ size_type size() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::null: { @@ -22168,13 +22175,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::size() - return m_value.array->size(); + return m_data.m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() - return m_value.object->size(); + return m_data.m_value.object->size(); } case value_t::string: @@ -22196,18 +22203,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/max_size/ size_type max_size() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::array: { // delegate call to array_t::max_size() - return m_value.array->max_size(); + return m_data.m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() - return m_value.object->max_size(); + return m_data.m_value.object->max_size(); } case value_t::null: @@ -22240,53 +22247,53 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/clear/ void clear() noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::number_integer: { - m_value.number_integer = 0; + m_data.m_value.number_integer = 0; break; } case value_t::number_unsigned: { - m_value.number_unsigned = 0; + m_data.m_value.number_unsigned = 0; break; } case value_t::number_float: { - m_value.number_float = 0.0; + m_data.m_value.number_float = 0.0; break; } case value_t::boolean: { - m_value.boolean = false; + m_data.m_value.boolean = false; break; } case value_t::string: { - m_value.string->clear(); + m_data.m_value.string->clear(); break; } case value_t::binary: { - m_value.binary->clear(); + m_data.m_value.binary->clear(); break; } case value_t::array: { - m_value.array->clear(); + m_data.m_value.array->clear(); break; } case value_t::object: { - m_value.object->clear(); + m_data.m_value.object->clear(); break; } @@ -22310,15 +22317,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_type = value_t::array; - m_value = value_t::array; + m_data.m_type = value_t::array; + m_data.m_value = value_t::array; assert_invariant(); } // add element to array (move semantics) - const auto old_capacity = m_value.array->capacity(); - m_value.array->push_back(std::move(val)); - set_parent(m_value.array->back(), old_capacity); + const auto old_capacity = m_data.m_value.array->capacity(); + m_data.m_value.array->push_back(std::move(val)); + set_parent(m_data.m_value.array->back(), old_capacity); // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor } @@ -22343,15 +22350,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_type = value_t::array; - m_value = value_t::array; + m_data.m_type = value_t::array; + m_data.m_value = value_t::array; assert_invariant(); } // add element to array - const auto old_capacity = m_value.array->capacity(); - m_value.array->push_back(val); - set_parent(m_value.array->back(), old_capacity); + const auto old_capacity = m_data.m_value.array->capacity(); + m_data.m_value.array->push_back(val); + set_parent(m_data.m_value.array->back(), old_capacity); } /// @brief add an object to an array @@ -22375,13 +22382,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_type = value_t::object; - m_value = value_t::object; + m_data.m_type = value_t::object; + m_data.m_value = value_t::object; assert_invariant(); } // add element to object - auto res = m_value.object->insert(val); + auto res = m_data.m_value.object->insert(val); set_parent(res.first->second); } @@ -22431,15 +22438,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_type = value_t::array; - m_value = value_t::array; + m_data.m_type = value_t::array; + m_data.m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) - const auto old_capacity = m_value.array->capacity(); - m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_value.array->back(), old_capacity); + const auto old_capacity = m_data.m_value.array->capacity(); + m_data.m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_data.m_value.array->back(), old_capacity); } /// @brief add an object to an object if key does not exist @@ -22456,13 +22463,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_type = value_t::object; - m_value = value_t::object; + m_data.m_type = value_t::object; + m_data.m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); + auto res = m_data.m_value.object->emplace(std::forward(args)...); set_parent(res.first->second); // create result iterator and set iterator to the result of emplace @@ -22480,14 +22487,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec iterator insert_iterator(const_iterator pos, Args&& ... args) { iterator result(this); - JSON_ASSERT(m_value.array != nullptr); + JSON_ASSERT(m_data.m_value.array != nullptr); - auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_value.array->begin() + insert_pos; + auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); + m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; // This could have been written as: - // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. set_parents(); @@ -22614,7 +22621,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); } - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); } /// @brief updates a JSON object from another object, overwriting existing keys @@ -22631,8 +22638,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_type = value_t::object; - m_value.object = create(); + m_data.m_type = value_t::object; + m_data.m_value.object = create(); assert_invariant(); } @@ -22657,16 +22664,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (merge_objects && it.value().is_object()) { - auto it2 = m_value.object->find(it.key()); - if (it2 != m_value.object->end()) + auto it2 = m_data.m_value.object->find(it.key()); + if (it2 != m_data.m_value.object->end()) { it2->second.update(it.value(), true); continue; } } - m_value.object->operator[](it.key()) = it.value(); + m_data.m_value.object->operator[](it.key()) = it.value(); #if JSON_DIAGNOSTICS - m_value.object->operator[](it.key()).m_parent = this; + m_data.m_value.object->operator[](it.key()).m_parent = this; #endif } } @@ -22680,8 +22687,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec std::is_nothrow_move_assignable::value ) { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); + std::swap(m_data.m_type, other.m_data.m_type); + std::swap(m_data.m_value, other.m_data.m_value); set_parents(); other.set_parents(); @@ -22708,7 +22715,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_array())) { using std::swap; - swap(*(m_value.array), other); + swap(*(m_data.m_value.array), other); } else { @@ -22724,7 +22731,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_object())) { using std::swap; - swap(*(m_value.object), other); + swap(*(m_data.m_value.object), other); } else { @@ -22740,7 +22747,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_string())) { using std::swap; - swap(*(m_value.string), other); + swap(*(m_data.m_value.string), other); } else { @@ -22756,7 +22763,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_binary())) { using std::swap; - swap(*(m_value.binary), other); + swap(*(m_data.m_value.binary), other); } else { @@ -22772,7 +22779,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_binary())) { using std::swap; - swap(*(m_value.binary), other); + swap(*(m_data.m_value.binary), other); } else { @@ -22800,31 +22807,31 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec switch (lhs_type) \ { \ case value_t::array: \ - return (*lhs.m_value.array) op (*rhs.m_value.array); \ + return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ \ case value_t::object: \ - return (*lhs.m_value.object) op (*rhs.m_value.object); \ + return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ \ case value_t::null: \ return (null_result); \ \ case value_t::string: \ - return (*lhs.m_value.string) op (*rhs.m_value.string); \ + return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ \ case value_t::boolean: \ - return (lhs.m_value.boolean) op (rhs.m_value.boolean); \ + return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ \ case value_t::number_integer: \ - return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \ + return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ \ case value_t::number_unsigned: \ - return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \ + return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ \ case value_t::number_float: \ - return (lhs.m_value.number_float) op (rhs.m_value.number_float); \ + return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ \ case value_t::binary: \ - return (*lhs.m_value.binary) op (*rhs.m_value.binary); \ + return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ \ case value_t::discarded: \ default: \ @@ -22833,27 +22840,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_value.number_integer) op rhs.m_value.number_float; \ + return static_cast(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ { \ - return lhs.m_value.number_float op static_cast(rhs.m_value.number_integer); \ + return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_integer); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \ + return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_value.number_float op static_cast(rhs.m_value.number_unsigned); \ + return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_unsigned); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ { \ - return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \ + return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_value.number_integer op static_cast(rhs.m_value.number_unsigned); \ + return lhs.m_data.m_value.number_integer op static_cast(rhs.m_data.m_value.number_unsigned); \ } \ else if(compares_unordered(lhs, rhs))\ {\ @@ -22870,8 +22877,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // an operation is computed as an odd number of inverses of others static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept { - if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number()) - || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number())) + if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) + || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) { return true; } @@ -23372,7 +23379,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_HEDLEY_RETURNS_NON_NULL const char* type_name() const noexcept { - switch (m_type) + switch (m_data.m_type) { case value_t::null: return "null"; @@ -23402,11 +23409,38 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // member variables // ////////////////////// - /// the type of the current element - value_t m_type = value_t::null; + struct data + { + /// the type of the current element + value_t m_type = value_t::null; - /// the value of the current element - json_value m_value = {}; + /// the value of the current element + json_value m_value = {}; + + data(const value_t v) + : m_type(v), m_value(v) + { + } + + data(size_type cnt, const basic_json& val) + : m_type(value_t::array) + { + m_value.array = create(cnt, val); + } + + data() noexcept = default; + data(data&&) noexcept = default; + data(const data&) noexcept = delete; + data& operator=(data&&) noexcept = delete; + data& operator=(const data&) noexcept = delete; + + ~data() noexcept + { + m_value.destroy(m_type); + } + }; + + data m_data = {}; #if JSON_DIAGNOSTICS /// a pointer to a parent value (for debugging purposes) @@ -23946,7 +23980,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // parent must exist when performing patch add per RFC6902 specs basic_json& parent = result.at(ptr); - switch (parent.m_type) + switch (parent.m_data.m_type) { case value_t::null: case value_t::object: @@ -24035,13 +24069,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec bool string_type) -> basic_json & { // find value - auto it = val.m_value.object->find(member); + auto it = val.m_data.m_value.object->find(member); // context-sensitive error message const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) + if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) { // NOLINTNEXTLINE(performance-inefficient-string-concatenation) JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); @@ -24635,4 +24669,6 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG #undef JSON_HEDLEY_FALL_THROUGH -#endif // INCLUDE_NLOHMANN_JSON_HPP_ + + +#endif // INCLUDE_NLOHMANN_JSON_HPP_ \ No newline at end of file diff --git a/runtime/common/scope.cpp b/runtime/common/scope.cpp index ea4711a0a..4c648a455 100644 --- a/runtime/common/scope.cpp +++ b/runtime/common/scope.cpp @@ -5,37 +5,47 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include -#include "scope-defs.h" +#include #define FRAME_FLUSH_SIZE 100 #define MMIO_SCOPE_READ (AFU_IMAGE_MMIO_SCOPE_READ * 4) #define MMIO_SCOPE_WRITE (AFU_IMAGE_MMIO_SCOPE_WRITE * 4) -#define CMD_GET_VALID 0 -#define CMD_GET_DATA 1 -#define CMD_GET_WIDTH 2 -#define CMD_GET_COUNT 3 -#define CMD_GET_START 4 -#define CMD_SET_START 5 -#define CMD_SET_STOP 6 +#define CMD_GET_WIDTH 0 +#define CMD_GET_COUNT 1 +#define CMD_GET_START 2 +#define CMD_GET_DATA 3 +#define CMD_SET_START 4 +#define CMD_SET_STOP 5 -static constexpr int num_modules = sizeof(scope_modules) / sizeof(scope_module_t); +struct tap_signal_t { + uint32_t id; + std::string name; + uint32_t width; +}; -static constexpr int num_taps = sizeof(scope_taps) / sizeof(scope_tap_t); +struct tap_t { + uint32_t id; + uint32_t width; + uint32_t frames; + uint32_t cur_frame; + uint64_t ticks; + std::string path; + std::vector signals; +}; -constexpr int calcFrameWidth(int index = 0) { - return (index < num_taps) ? (scope_taps[index].width + calcFrameWidth(index + 1)) : 0; -} - -static constexpr int fwidth = calcFrameWidth(); +using json = nlohmann::json; #ifdef HANG_TIMEOUT static std::thread g_timeout_thread; @@ -50,7 +60,7 @@ static void timeout_callback(vx_device_h hdevice) { std::cerr << "Scope timed out!" << std::endl; g_timeout_enabled = false; auto device = ((vx_device*)hdevice); - auto api = device->api; + auto& api = device->api; vx_scope_stop(hdevice); api.fpgaClose(device->fpga); exit(-1); @@ -60,7 +70,7 @@ static void timeout_callback(vx_device_h hdevice) { } #endif -uint64_t print_clock(std::ofstream& ofs, uint64_t delta, uint64_t timestamp) { +static uint64_t dump_clock(std::ofstream& ofs, uint64_t delta, uint64_t timestamp) { while (delta != 0) { ofs << '#' << timestamp++ << std::endl; ofs << "b0 0" << std::endl; @@ -71,54 +81,200 @@ uint64_t print_clock(std::ofstream& ofs, uint64_t delta, uint64_t timestamp) { return timestamp; } -void dump_taps(std::ofstream& ofs, int module) { - for (int i = 0; i < num_taps; ++i) { - auto& tap = scope_taps[i]; - if (tap.module != module) - continue; - ofs << "$var reg " << tap.width << " " << (i + 1) << " " << tap.name << " $end" << std::endl; +static std::vector split(const std::string &s, char delimiter) { + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); } + return tokens; } -void dump_module(std::ofstream& ofs, int parent) { - for (auto& module : scope_modules) { - if (module.parent != parent) - continue; - if (module.name[0] == '*') { - ofs << "$var reg 1 0 clk $end" << std::endl; - } else { - ofs << "$scope module " << module.name << " $end" << std::endl; - } - dump_module(ofs, module.index); - dump_taps(ofs, module.index); - if (module.name[0] != '*') { - ofs << "$upscope $end" << std::endl; +static void dump_module(std::ofstream& ofs, + const std::string& name, + std::unordered_map>& hierarchy, + std::unordered_map& tails, + int indentation) { + std::string indent(indentation, ' '); + ofs << indent << "$scope module " << name << " $end" << std::endl; + + auto itt = tails.find(name); + if (itt != tails.end()) { + for (auto& signal : itt->second->signals) { + ofs << indent << " $var reg " << signal.width << " " << signal.id << " " << signal.name << " $end" << std::endl; } } + + auto ith = hierarchy.find(name); + if (ith != hierarchy.end()) { + for (auto& child : ith->second) { + dump_module(ofs, child, hierarchy, tails, indentation + 1); + } + } + + ofs << indent << "$upscope $end" << std::endl; +} + +static void dump_header(std::ofstream& ofs, std::vector& taps) { + ofs << "$version Generated by Vortex Scope Analyzer $end" << std::endl; + ofs << "$timescale 1 ns $end" << std::endl; + ofs << "$scope module TOP $end" << std::endl; + ofs << " $var reg 1 0 clk $end" << std::endl; + + std::unordered_map> hierarchy; + std::unordered_set heads; + std::unordered_map tails; + + // Build hierarchy + for (auto& tap : taps) { + std::vector tokens = split(tap.path, '.'); + for (size_t i = 1; i < tokens.size(); ++i) { + hierarchy[tokens[i-1]].insert(tokens[i]); + } + auto h = tokens[0]; + auto t = tokens[tokens.size()-1]; + heads.insert(h); + tails[t] = &tap; + } + + // Dump module huierarchy + for (auto& head : heads) { + dump_module(ofs, head, hierarchy, tails, 1); + } + + ofs << "$upscope $end" << std::endl; + ofs << "enddefinitions $end" << std::endl; +} + +static tap_t* find_nearest_tap(std::vector& taps) { + tap_t* nearest = nullptr; + for (auto& tap : taps) { + if (tap.cur_frame == tap.frames) + continue; + if (nearest != nullptr) { + if (tap.ticks < nearest->ticks) + nearest = &tap; + } else { + nearest = &tap; + } + } + return nearest; +} + +static void dump_tap(std::ofstream& ofs, tap_t* tap, vx_device* device) { + auto& api = device->api; + + uint32_t signal_offset = 0; + uint32_t frame_offset = 0; + uint64_t word; + + std::vector signal_data(tap->width); + auto signal_it = tap->signals.rbegin(); + uint32_t signal_width = signal_it->width; + + do { + // read data + uint64_t cmd_data = (tap->id << 3) | CMD_GET_DATA; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_data), { + return; + }); + CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &word), { + return; + }); + do { + uint32_t word_offset = frame_offset % 64; + signal_data[signal_width - signal_offset - 1] = ((word >> word_offset) & 0x1) ? '1' : '0'; + ++signal_offset; + ++frame_offset; + if (signal_offset == signal_width) { + signal_data[signal_width] = 0; // string null termination + ofs << 'b' << signal_data.data() << ' ' << signal_it->id << std::endl; + if (frame_offset == tap->width) { + // end-of-frame + ++tap->cur_frame; + if (tap->cur_frame != tap->frames) { + // read next delta + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_data), { + return; + }); + CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &word), { + return; + }); + tap->ticks += word; + + if (0 == (tap->cur_frame % FRAME_FLUSH_SIZE)) { + ofs << std::flush; + std::cout << std::dec << "*** scope #" << tap->id << ": "<< tap->cur_frame << "/" << tap->frames << " frames" << std::endl; + } + } + break; + } + signal_offset = 0; + ++signal_it; + signal_width = signal_it->width; + } + } while ((frame_offset % 64) != 0); + } while (frame_offset != tap->width); } int vx_scope_start(vx_device_h hdevice, uint64_t start_time, uint64_t stop_time) { if (nullptr == hdevice) return -1; + const char* json_path = getenv("SCOPE_JSON_PATH"); + std::ifstream ifs(json_path); + if (!ifs) + return -1; + auto json_obj = json::parse(ifs); + if (json_obj.is_null()) + return -1; + auto device = ((vx_device*)hdevice); - auto api = device->api; - - if (stop_time != uint64_t(-1)) { - // set stop time - uint64_t cmd_stop = ((stop_time << 3) | CMD_SET_STOP); - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_stop), { + auto& api = device->api; + + // validate scope manifest + for (auto& tap : json_obj["taps"]) { + auto id = tap["id"].get(); + auto width = tap["width"].get(); + + uint64_t cmd_width = (id << 3) | CMD_GET_WIDTH; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_width), { return -1; }); - std::cout << "scope stop time: " << std::dec << stop_time << "s" << std::endl; + uint64_t dev_width; + CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &dev_width), { + return -1; + }); + if (width != dev_width) { + std::cerr << "Invalid scope with! id=" << id << ", actual=" << dev_width << ", expected=" << width << std::endl; + return 1; + } } - + + // set stop time + if (stop_time != uint64_t(-1)) { + std::cout << "scope stop time: " << std::dec << stop_time << "s" << std::endl; + for (auto& tap : json_obj["taps"]) { + auto id = tap["id"].get(); + uint64_t cmd_stop = (stop_time << 11) | (id << 3) | CMD_SET_STOP; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_stop), { + return -1; + }); + } + } + // start recording - uint64_t cmd_delay = ((start_time << 3) | CMD_SET_START); - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_delay), { - return -1; - }); - std::cout << "scope start time: " << std::dec << start_time << "s" << std::endl; + if (start_time != uint64_t(-1)) { + std::cout << "scope start time: " << std::dec << start_time << "s" << std::endl; + for (auto& tap : json_obj["taps"]) { + auto id = tap["id"].get(); + uint64_t cmd_start = (start_time << 11) | (id << 3) | CMD_SET_START; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_start), { + return -1; + }); + } + } #ifdef HANG_TIMEOUT // starting timeout thread @@ -129,7 +285,7 @@ int vx_scope_start(vx_device_h hdevice, uint64_t start_time, uint64_t stop_time) return 0; } -int vx_scope_stop(vx_device_h hdevice) { +int vx_scope_stop(vx_device_h hdevice) { #ifdef HANG_TIMEOUT if (g_timeout_enabled) { // shutting down timeout thread @@ -142,163 +298,105 @@ int vx_scope_stop(vx_device_h hdevice) { if (nullptr == hdevice) return -1; - auto device = ((vx_device*)hdevice); - auto api = device->api; + auto device = (vx_device*)hdevice; + auto& api = device->api; - // forced stop - uint64_t cmd_stop = ((0 << 3) | CMD_SET_STOP); - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_stop), { - return -1; - }); + std::vector taps; + + { + const char* json_path = getenv("SCOPE_JSON_PATH"); + std::ifstream ifs(json_path); + auto json_obj = json::parse(ifs); + if (json_obj.is_null()) + return 0; + + uint32_t signal_id = 1; + + for (auto& tap : json_obj["taps"]) { + tap_t _tap; + _tap.id = tap["id"].get(); + _tap.width = tap["width"].get(); + _tap.path = tap["path"].get(); + _tap.ticks = 0; + _tap.frames = 0; + _tap.cur_frame = 0; + + for (auto& signal : tap["signals"]) { + auto name = signal[0].get(); + auto width = signal[1].get(); + _tap.signals.push_back({signal_id, name, width}); + ++signal_id; + } + + taps.emplace_back(std::move(_tap)); + } + } + + // stop recording + for (auto& tap : taps) { + uint64_t cmd_stop = (0 << 11) | (tap.id << 3) | CMD_SET_STOP; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_stop), { + return -1; + }); + } std::cout << "scope trace dump begin..." << std::endl; - std::ofstream ofs("trace.vcd"); + std::ofstream ofs("scope.vcd"); - ofs << "$version Generated by Vortex Scope $end" << std::endl; - ofs << "$timescale 1 ns $end" << std::endl; - ofs << "$scope module TOP $end" << std::endl; - - dump_module(ofs, -1); - dump_taps(ofs, -1); - ofs << "$upscope $end" << std::endl; - ofs << "enddefinitions $end" << std::endl; + dump_header(ofs, taps); + + // load trace info + for (auto& tap : taps) { + uint64_t count, start, delta; + + // get count + uint64_t cmd_count = (tap.id << 3) | CMD_GET_COUNT; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_count), { + return -1; + }); + CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &count), { + return -1; + }); + + // get start + uint64_t cmd_start = (tap.id << 3) | CMD_GET_START; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_start), { + return -1; + }); + CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &start), { + return -1; + }); + + // get data + uint64_t cmd_data = (tap.id << 3) | CMD_GET_DATA; + CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, cmd_data), { + return -1; + }); + CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &delta), { + return -1; + }); + + tap.frames = count; + tap.ticks = start + delta; + + std::cout << std::dec << "scope #" << tap.id << ": width=" << tap.width << ", num_frames=" << tap.frames << ", start_time=" << tap.ticks << ", path=" << tap.path << std::endl; + } - uint64_t frame_width, max_frames, data_valid, offset, delta; uint64_t timestamp = 0; - uint64_t frame_offset = 0; - uint64_t frame_no = 0; - int signal_id = 0; - int signal_offset = 0; - // wait for recording to terminate - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_VALID), { - return -1; - }); - do { - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &data_valid), { - return -1; - }); - if (data_valid) + while (true) { + // find the nearest tap + auto tap = find_nearest_tap(taps); + if (tap == nullptr) break; - std::this_thread::sleep_for(std::chrono::seconds(1)); - } while (true); - - // get frame width - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_WIDTH), { - return -1; - }); - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &frame_width), { - return -1; - }); - std::cout << "scope::frame_width=" << std::dec << frame_width << std::endl; - - if (fwidth != (int)frame_width) { - std::cerr << "invalid frame_width: expecting " << std::dec << fwidth << "!" << std::endl; - std::abort(); - } - - // get max frames - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_COUNT), { - return -1; - }); - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &max_frames), { - return -1; - }); - std::cout << "scope::max_frames=" << std::dec << max_frames << std::endl; - - // get offset - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_START), { - return -1; - }); - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &offset), { - return -1; - }); - - // get data - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_DATA), { - return -1; - }); - - // print clock header - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &delta), { - return -1; - }); - timestamp = print_clock(ofs, offset + delta + 2, timestamp); - signal_id = num_taps; - - std::vector signal_data(frame_width+1); - - do { - if (frame_no == (max_frames-1)) { - // verify last frame is valid - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_VALID), { - return -1; - }); - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &data_valid), { - return -1; - }); - assert(data_valid == 1); - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_DATA), { - return -1; - }); - } - - // read next data words - uint64_t word; - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &word), { - return -1; - }); - - do { - int signal_width = scope_taps[signal_id-1].width; - int word_offset = frame_offset % 64; - - signal_data[signal_width - signal_offset - 1] = ((word >> word_offset) & 0x1) ? '1' : '0'; - - ++signal_offset; - ++frame_offset; - - if (signal_offset == signal_width) { - signal_data[signal_width] = 0; // string null termination - ofs << 'b' << signal_data.data() << ' ' << signal_id << std::endl; - signal_offset = 0; - --signal_id; - } - - if (frame_offset == frame_width) { - assert(0 == signal_offset); - frame_offset = 0; - ++frame_no; - - if (frame_no != max_frames) { - // print clock header - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &delta), { - return -1; - }); - timestamp = print_clock(ofs, delta + 1, timestamp); - signal_id = num_taps; - if (0 == (frame_no % FRAME_FLUSH_SIZE)) { - ofs << std::flush; - std::cout << "*** " << frame_no << "/" << max_frames << " frames" << std::endl; - } - } - } - - } while ((frame_offset % 64) != 0); - - } while (frame_no != max_frames); + // advance clock + timestamp = dump_clock(ofs, tap->ticks + 1, timestamp); + // dump tap + dump_tap(ofs, tap, device); + }; std::cout << "scope trace dump done! - " << (timestamp/2) << " cycles" << std::endl; - // verify data not valid - CHECK_ERR(api.fpgaWriteMMIO64(device->fpga, 0, MMIO_SCOPE_WRITE, CMD_GET_VALID), { - return -1; - }); - CHECK_ERR(api.fpgaReadMMIO64(device->fpga, 0, MMIO_SCOPE_READ, &data_valid), { - return -1; - }); - assert(data_valid == 0); - return 0; -} \ No newline at end of file +} diff --git a/runtime/common/scope.h b/runtime/common/scope.h index 6c869429b..523fba23a 100644 --- a/runtime/common/scope.h +++ b/runtime/common/scope.h @@ -10,4 +10,4 @@ int vx_scope_start(vx_device_h hdevice, uint64_t start_time = 0, uint64_t stop_time = -1); -int vx_scope_stop(vx_device_h hdevice); \ No newline at end of file +int vx_scope_stop(vx_device_h hdevice); diff --git a/runtime/opae/Makefile b/runtime/opae/Makefile index 410ae006f..0850440c2 100644 --- a/runtime/opae/Makefile +++ b/runtime/opae/Makefile @@ -34,6 +34,7 @@ SRCS = vortex.cpp driver.cpp ../common/utils.cpp # set up target types ifeq ($(TARGET), opaesim) CXXFLAGS += -DOPAESIM + OPAESIM = libopae-c-sim.so else ifeq ($(TARGET), asesim) CXXFLAGS += -DASESIM @@ -47,15 +48,13 @@ ifdef DEBUG CXXFLAGS += -g -O0 else CXXFLAGS += -O2 -DNDEBUG - SCOPE_FLAGS += -D NDEBUG endif # Enable scope analyzer ifdef SCOPE CXXFLAGS += -DSCOPE SRCS += ../common/scope.cpp - SCOPE_H = scope-defs.h - SCOPE_FLAGS += -D SCOPE + SCOPE_JSON = scope.json endif # Enable perf counters @@ -67,20 +66,18 @@ PROJECT = libvortex.so all: $(PROJECT) -scope-defs.h: $(SCRIPT_DIR)/scope.json - $(SCRIPT_DIR)/scope.py $(CONFIGS) $(SCOPE_FLAGS) -cc scope-defs.h -vl $(RTL_DIR)/scope-defs.vh $(SCRIPT_DIR)/scope.json +vortex.xml: + DESTDIR=../../runtime/opae $(MAKE) -C $(OPAESIM_DIR) ../../runtime/opae/vortex.xml -# generate scope data -scope: scope-defs.h +scope.json: vortex.xml + $(SCRIPT_DIR)/scope.py vortex.xml -o scope.json -$(PROJECT): $(SRCS) $(SCOPE_H) -ifeq ($(TARGET), opaesim) - $(MAKE) -C $(OPAESIM_DIR) -endif +libopae-c-sim.so: + DESTDIR=../../runtime/opae $(MAKE) -C $(OPAESIM_DIR) ../../runtime/opae/libopae-c-sim.so + +$(PROJECT): $(SRCS) $(OPAESIM) $(SCOPE_JSON) $(CXX) $(CXXFLAGS) $(SRCS) $(LDFLAGS) -o $(PROJECT) clean: - rm -rf $(PROJECT) *.o scope-defs.h $(RTL_DIR)/scope-defs.vh -ifeq ($(TARGET), opaesim) - $(MAKE) -C $(OPAESIM_DIR) clean -endif + DESTDIR=../../runtime/opae $(MAKE) -C $(OPAESIM_DIR) clean + rm -rf $(PROJECT) vortex.xml scope.json diff --git a/runtime/opae/vortex.cpp b/runtime/opae/vortex.cpp index 6355db9ba..6fed31dbb 100755 --- a/runtime/opae/vortex.cpp +++ b/runtime/opae/vortex.cpp @@ -212,7 +212,7 @@ extern int vx_dev_close(vx_device_h hdevice) { return -1; auto device = ((vx_device*)hdevice); - auto api = device->api; + auto& api = device->api; #ifdef SCOPE vx_scope_stop(hdevice); @@ -275,7 +275,7 @@ extern int vx_buf_alloc(vx_device_h hdevice, uint64_t size, vx_buffer_h* hbuffer return -1; auto device = ((vx_device*)hdevice); - auto api = device->api; + auto& api = device->api; size_t asize = aligned_size(size, CACHE_BLOCK_SIZE); @@ -321,7 +321,7 @@ extern int vx_buf_free(vx_buffer_h hbuffer) { auto buffer = ((vx_buffer_t*)hbuffer); auto device = ((vx_device*)buffer->hdevice); - auto api = device->api; + auto& api = device->api; api.fpgaReleaseBuffer(device->fpga, buffer->wsid); @@ -337,7 +337,7 @@ extern int vx_ready_wait(vx_device_h hdevice, uint64_t timeout) { std::unordered_map print_bufs; auto device = ((vx_device*)hdevice); - auto api = device->api; + auto& api = device->api; struct timespec sleep_time; @@ -402,7 +402,7 @@ extern int vx_copy_to_dev(vx_buffer_h hbuffer, uint64_t dev_maddr, uint64_t size auto buffer = ((vx_buffer_t*)hbuffer); auto device = ((vx_device*)buffer->hdevice); - auto api = device->api; + auto& api = device->api; uint64_t dev_mem_size = LOCAL_MEM_SIZE; uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE); @@ -452,7 +452,7 @@ extern int vx_copy_from_dev(vx_buffer_h hbuffer, uint64_t dev_maddr, uint64_t si auto buffer = ((vx_buffer_t*)hbuffer); auto device = ((vx_device*)buffer->hdevice); - auto api = device->api; + auto& api = device->api; uint64_t dev_mem_size = LOCAL_MEM_SIZE; uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE); @@ -500,7 +500,7 @@ extern int vx_start(vx_device_h hdevice) { return -1; auto device = ((vx_device*)hdevice); - auto api = device->api; + auto& api = device->api; // Ensure ready for new command if (vx_ready_wait(hdevice, MAX_TIMEOUT) != 0) @@ -519,7 +519,7 @@ extern int vx_dcr_write(vx_device_h hdevice, uint32_t addr, uint64_t value) { return -1; auto device = ((vx_device*)hdevice); - auto api = device->api; + auto& api = device->api; // Ensure ready for new command if (vx_ready_wait(hdevice, -1) != 0) diff --git a/sim/opaesim/Makefile b/sim/opaesim/Makefile index cb1acc3ed..76ca2cf57 100644 --- a/sim/opaesim/Makefile +++ b/sim/opaesim/Makefile @@ -45,8 +45,8 @@ RTL_INCLUDE += -I$(AFU_DIR) -I$(AFU_DIR)/ccip TOP = vortex_afu_shim -VL_FLAGS = --exe --cc $(TOP) --top-module $(TOP) -VL_FLAGS += -O2 --language 1800-2009 --assert -Wall -Wpedantic +VL_FLAGS = --cc $(TOP) --top-module $(TOP) +VL_FLAGS += --language 1800-2009 --assert -Wall -Wpedantic VL_FLAGS += -Wno-DECLFILENAME -Wno-REDEFMACRO VL_FLAGS += --x-initial unique --x-assign unique VL_FLAGS += -DSIMULATION @@ -67,7 +67,7 @@ ifdef DEBUG CXXFLAGS += -g -O0 $(DBG_FLAGS) else VL_FLAGS += -DNDEBUG - CXXFLAGS += -O2 -DNDEBUG + CXXFLAGS += -O3 -DNDEBUG endif # Enable scope analyzer @@ -102,7 +102,10 @@ vortex_afu.h : $(AFU_DIR)/vortex_afu.vh $(SCRIPT_DIR)/gen_config.py -i $(AFU_DIR)/vortex_afu.vh -o vortex_afu.h $(DESTDIR)/$(PROJECT): $(SRCS) vortex_afu.h - verilator --build $(VL_FLAGS) $(SRCS) -CFLAGS '$(CXXFLAGS)' -LDFLAGS '$(LDFLAGS)' -o ../$(DESTDIR)/$(PROJECT) + verilator --build --exe -O3 $(VL_FLAGS) $(SRCS) -CFLAGS '$(CXXFLAGS)' -LDFLAGS '$(LDFLAGS)' -o ../$(DESTDIR)/$(PROJECT) + +$(DESTDIR)/vortex.xml: $(DESTDIR)/$(PROJECT) + verilator --xml-only -O0 $(VL_FLAGS) --xml-output $(DESTDIR)/vortex.xml clean: rm -rf obj_dir $(DESTDIR)/$(PROJECT) diff --git a/sim/opaesim/opae_sim.cpp b/sim/opaesim/opae_sim.cpp index 45e382275..33c2026d1 100644 --- a/sim/opaesim/opae_sim.cpp +++ b/sim/opaesim/opae_sim.cpp @@ -63,6 +63,8 @@ #define RAM_PAGE_SIZE 4096 +#define CPU_GPU_LATENCY 200 + using namespace vortex; static uint64_t timestamp = 0; @@ -193,6 +195,11 @@ public: void read_mmio64(uint32_t mmio_num, uint64_t offset, uint64_t *value) { std::lock_guard guard(mutex_); + // simulate CPU-GPU latency + for (uint32_t i = 0; i < CPU_GPU_LATENCY; ++i) + this->tick(); + + // simulate mmio request device_->vcp2af_sRxPort_c0_mmioRdValid = 1; device_->vcp2af_sRxPort_c0_ReqMmioHdr_address = offset / 4; device_->vcp2af_sRxPort_c0_ReqMmioHdr_length = 1; @@ -205,7 +212,12 @@ public: void write_mmio64(uint32_t mmio_num, uint64_t offset, uint64_t value) { std::lock_guard guard(mutex_); + + // simulate CPU-GPU latency + for (uint32_t i = 0; i < CPU_GPU_LATENCY; ++i) + this->tick(); + // simulate mmio request device_->vcp2af_sRxPort_c0_mmioWrValid = 1; device_->vcp2af_sRxPort_c0_ReqMmioHdr_address = offset / 4; device_->vcp2af_sRxPort_c0_ReqMmioHdr_length = 1; diff --git a/tests/opencl/common.mk b/tests/opencl/common.mk index e13c78f93..17660f605 100644 --- a/tests/opencl/common.mk +++ b/tests/opencl/common.mk @@ -35,12 +35,12 @@ else endif ifeq ($(TARGET), fpga) - OPAE_DRV_PATHS ?= $(OPAE_SDK_ROOT)/lib64/libopae-c.so + OPAE_DRV_PATHS ?= libopae-c.so else ifeq ($(TARGET), asesim) - OPAE_DRV_PATHS ?= $(OPAE_SDK_ROOT)/lib64/libopae-c-ase.so + OPAE_DRV_PATHS ?= libopae-c-ase.so else - OPAE_DRV_PATHS ?= ../../../sim/opaesim/libopae-c-sim.so + OPAE_DRV_PATHS ?= libopae-c-sim.so endif endif @@ -59,7 +59,7 @@ run-rtlsim: $(PROJECT) kernel.pocl LD_LIBRARY_PATH=$(POCL_RT_PATH)/lib:$(VORTEX_RT_PATH)/rtlsim:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS) run-opae: $(PROJECT) kernel.pocl - OPAE_DRV_PATHS=$(OPAE_DRV_PATHS) LD_LIBRARY_PATH=$(POCL_RT_PATH)/lib:$(VORTEX_RT_PATH)/opae:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS) + OPAE_DRV_PATHS=$(OPAE_DRV_PATHS) SCOPE_JSON_PATH=$(VORTEX_RT_PATH)/opae/scope.json LD_LIBRARY_PATH=$(POCL_RT_PATH)/lib:$(VORTEX_RT_PATH)/opae:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS) run-xrt: $(PROJECT) kernel.pocl ifeq ($(TARGET), hw) diff --git a/tests/regression/common.mk b/tests/regression/common.mk index 010b043c9..eec80ba67 100644 --- a/tests/regression/common.mk +++ b/tests/regression/common.mk @@ -54,12 +54,12 @@ else endif ifeq ($(TARGET), fpga) - OPAE_DRV_PATHS ?= $(OPAE_SDK_ROOT)/lib64/libopae-c.so + OPAE_DRV_PATHS ?= libopae-c.so else ifeq ($(TARGET), asesim) - OPAE_DRV_PATHS ?= $(OPAE_SDK_ROOT)/lib64/libopae-c-ase.so + OPAE_DRV_PATHS ?= libopae-c-ase.so else - OPAE_DRV_PATHS ?= ../../../sim/opaesim/libopae-c-sim.so + OPAE_DRV_PATHS ?= libopae-c-sim.so endif endif @@ -81,7 +81,7 @@ run-simx: $(PROJECT) kernel.bin LD_LIBRARY_PATH=$(VORTEX_RT_PATH)/simx:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS) run-opae: $(PROJECT) kernel.bin - OPAE_DRV_PATHS=$(OPAE_DRV_PATHS) LD_LIBRARY_PATH=$(VORTEX_RT_PATH)/opae:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS) + OPAE_DRV_PATHS=$(OPAE_DRV_PATHS) SCOPE_JSON_PATH=$(VORTEX_RT_PATH)/opae/scope.json LD_LIBRARY_PATH=$(HOME)/dev/netlist-paths/release/install/lib:$(VORTEX_RT_PATH)/opae:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS) run-rtlsim: $(PROJECT) kernel.bin LD_LIBRARY_PATH=$(VORTEX_RT_PATH)/rtlsim:$(LD_LIBRARY_PATH) ./$(PROJECT) $(OPTS)