// © IBM Corp. 2020 // Licensed under the Apache License, Version 2.0 (the "License"), as modified by // the terms below; you may not use the files in this repository except in // compliance with the License as modified. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 // // Modified Terms: // // 1) For the purpose of the patent license granted to you in Section 3 of the // License, the "Work" hereby includes implementations of the work of authorship // in physical form. // // 2) Notwithstanding any terms to the contrary in the License, any licenses // necessary for implementation of the Work that are available from OpenPOWER // via the Power ISA End User License Agreement (EULA) are explicitly excluded // hereunder, and may be obtained from OpenPOWER under the terms and conditions // of the EULA. // // Unless required by applicable law or agreed to in writing, the reference design // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License // for the specific language governing permissions and limitations under the License. // // Additional rights, including the ability to physically implement a softcore that // is compliant with the required sections of the Power ISA Specification, are // available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be // obtained (along with the Power ISA) here: https://openpowerfoundation.org. `timescale 1 ns / 1 ns // ********************************************************************* // // This is the ENTITY for rv_perv // // ********************************************************************* module rv_perv( // 0 = ibm umbra, 1 = xilinx, 2 = ibm mpg `include "tri_a2o.vh" inout vdd, inout gnd, (* pin_data="PIN_FUNCTION=/G_CLK/CAP_LIMIT=/99999/" *) // nclk input [0:`NCLK_WIDTH-1] nclk, input rp_rv_ccflush_dc, input rp_rv_func_sl_thold_3, input rp_rv_gptr_sl_thold_3, input rp_rv_sg_3, input rp_rv_fce_3, input an_ac_scan_diag_dc, input an_ac_scan_dis_dc_b, input d_mode, output func_sl_thold_1, output fce_1, output sg_1, output clkoff_dc_b, output act_dis, output [0:9] delay_lclkr_dc, output [0:9] mpw1_dc_b, output mpw2_dc_b, input gptr_scan_in, output gptr_scan_out, input scan_in, output scan_out, //------------------------------------------------------------------------------------------------------------ // Debug and Perf //------------------------------------------------------------------------------------------------------------ input [0:8*`THREADS-1] fx0_rvs_perf_bus, input [0:31] fx0_rvs_dbg_bus, input [0:8*`THREADS-1] fx1_rvs_perf_bus, input [0:31] fx1_rvs_dbg_bus, input [0:8*`THREADS-1] lq_rvs_perf_bus, input [0:31] lq_rvs_dbg_bus, input [0:8*`THREADS-1] axu0_rvs_perf_bus, input [0:31] axu0_rvs_dbg_bus, input [0:`THREADS-1] spr_msr_gs, input [0:`THREADS-1] spr_msr_pr, input pc_rv_trace_bus_enable, input [0:10] pc_rv_debug_mux_ctrls, input pc_rv_event_bus_enable, input [0:2] pc_rv_event_count_mode, input [0:39] pc_rv_event_mux_ctrls, input [0:4*`THREADS-1] rv_event_bus_in, output [0:4*`THREADS-1] rv_event_bus_out, output [0:31] debug_bus_out, input [0:31] debug_bus_in, input [0:3] coretrace_ctrls_in, output [0:3] coretrace_ctrls_out ); wire func_sl_thold_2; wire gptr_sl_thold_2; wire sg_2; wire fce_2; wire gptr_sl_thold_1; wire func_sl_thold_1_int; wire sg_1_int; wire gptr_sl_thold_0; wire func_sl_thold_0; wire force_t; wire sg_0; wire gptr_sio; wire [0:9] prv_delay_lclkr_dc; wire [0:9] prv_mpw1_dc_b; wire prv_mpw2_dc_b; wire prv_act_dis; wire prv_clkoff_dc_b; // Debug and Perf wire trc_act; wire evt_act; wire delay_lclkr; wire mpw1_b; wire mpw2_b; wire [0:31] debug_bus_mux; wire [0:3] coretrace_ctrls_mux; wire [0:10] debug_mux_ctrls; wire [0:39] event_mux_ctrls; wire [0:2] event_count_mode; wire [0:`THREADS-1] spr_msr_gs_q; wire [0:`THREADS-1] spr_msr_pr_q; wire [0:`THREADS-1] event_en; wire [0:32*`THREADS-1] event_bus_in; wire [0:4*`THREADS-1] event_bus_d; wire [0:4*`THREADS-1] event_bus_q; wire [0:31] dbg_group0; wire [0:31] dbg_group1; wire [0:31] dbg_group2; wire [0:31] dbg_group3; // Unused Signals (* analysis_not_referenced="TRUE" *) wire act0_dis_dc; (* analysis_not_referenced="TRUE" *) wire d0_mode_dc; (* analysis_not_referenced="TRUE" *) wire clkoff1_dc_b; (* analysis_not_referenced="TRUE" *) wire act1_dis_dc; (* analysis_not_referenced="TRUE" *) wire d1_mode_dc; (* analysis_not_referenced="TRUE" *) wire nc_mpw2_dc_b; (* analysis_not_referenced="TRUE" *) wire unused; wire func_sl_thold_0_b = 0; // wtf: dangling test sig //------------------------------------------------------------------------------------------------------------ // Scan Chains //------------------------------------------------------------------------------------------------------------ parameter debug_bus_offset = 0 + 0; parameter debug_mux_offset = debug_bus_offset + 32; parameter event_bus_offset = debug_mux_offset + 11; parameter event_count_offset = event_bus_offset + 4*`THREADS; parameter spr_msr_gs_offset = event_count_offset + 3; parameter spr_msr_pr_offset = spr_msr_gs_offset + `THREADS; parameter event_mux_ctrls_offset = spr_msr_pr_offset + `THREADS; parameter coretrace_ctrls_offset = event_mux_ctrls_offset + 40; parameter scan_right = coretrace_ctrls_offset + 4; wire [0:scan_right-1] siv; wire [0:scan_right-1] sov; assign unused = an_ac_scan_dis_dc_b ; tri_plat #(.WIDTH(4)) perv_3to2_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .flush(rp_rv_ccflush_dc), .din({rp_rv_func_sl_thold_3, rp_rv_gptr_sl_thold_3, rp_rv_sg_3, rp_rv_fce_3}), .q({func_sl_thold_2, gptr_sl_thold_2, sg_2, fce_2}) ); tri_plat #(.WIDTH(4)) perv_2to1_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .flush(rp_rv_ccflush_dc), .din({func_sl_thold_2, gptr_sl_thold_2, sg_2, fce_2}), .q({func_sl_thold_1_int, gptr_sl_thold_1, sg_1_int, fce_1}) ); assign func_sl_thold_1 = func_sl_thold_1_int; assign sg_1 = sg_1_int; tri_plat #(.WIDTH(3)) perv_1to0_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .flush(rp_rv_ccflush_dc), .din({gptr_sl_thold_1 , func_sl_thold_1_int, sg_1_int}), .q({gptr_sl_thold_0, func_sl_thold_0, sg_0}) ); tri_lcbor perv_lcbor( .clkoff_b(prv_clkoff_dc_b), .thold(func_sl_thold_0), .sg(sg_0), .act_dis(prv_act_dis), .force_t(force_t), .thold_b(func_sl_thold_0_b) ); // Pipeline mapping of mpw1_b and delay_lclkr // RF0 // RF1 0 // EX1 1 // EX2 2 // EX3 3 // EX4 4 // EX5 5 // EX6 6 // EX7 7 tri_lcbcntl_mac perv_lcbctrl0( .vdd(vdd), .gnd(gnd), .sg(sg_0), .nclk(nclk), .scan_in(gptr_scan_in), .scan_diag_dc(an_ac_scan_diag_dc), .thold(gptr_sl_thold_0), .clkoff_dc_b(prv_clkoff_dc_b), .delay_lclkr_dc(prv_delay_lclkr_dc[0:4]), .act_dis_dc(act0_dis_dc), .d_mode_dc(d0_mode_dc), .mpw1_dc_b(prv_mpw1_dc_b[0:4]), .mpw2_dc_b(prv_mpw2_dc_b), .scan_out(gptr_sio) ); tri_lcbcntl_mac perv_lcbctrl1( .vdd(vdd), .gnd(gnd), .sg(sg_0), .nclk(nclk), .scan_in(gptr_sio), .scan_diag_dc(an_ac_scan_diag_dc), .thold(gptr_sl_thold_0), .clkoff_dc_b(clkoff1_dc_b), .delay_lclkr_dc(prv_delay_lclkr_dc[5:9]), .act_dis_dc(act1_dis_dc), .d_mode_dc(d1_mode_dc), .mpw1_dc_b(prv_mpw1_dc_b[5:9]), .mpw2_dc_b(nc_mpw2_dc_b), .scan_out(gptr_scan_out) ); //Outputs assign delay_lclkr_dc[0:9] = prv_delay_lclkr_dc[0:9]; assign mpw1_dc_b[0:9] = prv_mpw1_dc_b[0:9]; assign mpw2_dc_b = prv_mpw2_dc_b; //never disable act pins, they are used functionally assign prv_act_dis = 1'b0; assign act_dis = prv_act_dis; assign clkoff_dc_b = prv_clkoff_dc_b; //------------------------------------------------------------------------------------------------------------ // Perf bus //------------------------------------------------------------------------------------------------------------ assign event_en = ( spr_msr_pr_q & {`THREADS{event_count_mode[0]}}) | //-- User ((~spr_msr_pr_q) & spr_msr_gs_q & {`THREADS{event_count_mode[1]}}) | //-- Guest Supervisor ((~spr_msr_pr_q) & (~spr_msr_gs_q) & {`THREADS{event_count_mode[2]}}); //-- Hypervisor assign event_bus_in[ 0: 7] = fx0_rvs_perf_bus[0:7] & {8{event_en[0]}}; assign event_bus_in[ 8:15] = fx1_rvs_perf_bus[0:7] & {8{event_en[0]}}; assign event_bus_in[16:23] = lq_rvs_perf_bus[0:7] & {8{event_en[0]}}; assign event_bus_in[24:31] = axu0_rvs_perf_bus[0:7] & {8{event_en[0]}}; tri_event_mux1t #(.EVENTS_IN(32), .EVENTS_OUT(4)) event_mux0( .vd(vdd), .gd(gnd), .event_bus_in(rv_event_bus_in[0:3]), .event_bus_out(event_bus_d[0:3]), .unit_events_in(event_bus_in[1:31]), .select_bits(event_mux_ctrls[0:19]) ); `ifndef THREADS1 assign event_bus_in[32:39] = fx0_rvs_perf_bus[8:15] & {8{event_en[1]}}; assign event_bus_in[40:47] = fx1_rvs_perf_bus[8:15] & {8{event_en[1]}}; assign event_bus_in[48:55] = lq_rvs_perf_bus[8:15] & {8{event_en[1]}}; assign event_bus_in[56:63] = axu0_rvs_perf_bus[8:15] & {8{event_en[1]}}; tri_event_mux1t #(.EVENTS_IN(32), .EVENTS_OUT(4)) event_mux1( .vd(vdd), .gd(gnd), .event_bus_in(rv_event_bus_in[4:7]), .event_bus_out(event_bus_d[4:7]), .unit_events_in(event_bus_in[32:63]), .select_bits(event_mux_ctrls[20:39]) ); `endif assign rv_event_bus_out = event_bus_q; //------------------------------------------------------------------------------------------------------------ // Debug bus //------------------------------------------------------------------------------------------------------------ assign dbg_group0 = fx0_rvs_dbg_bus[0:31] ; assign dbg_group1 = fx1_rvs_dbg_bus[0:31] ; assign dbg_group2 = lq_rvs_dbg_bus[0:31] ; assign dbg_group3 = axu0_rvs_dbg_bus[0:31] ; tri_debug_mux4 #(.DBG_WIDTH(32)) dbg_mux( .select_bits(debug_mux_ctrls), .trace_data_in(debug_bus_in), .dbg_group0(dbg_group0), .dbg_group1(dbg_group1), .dbg_group2(dbg_group2), .dbg_group3(dbg_group3), .trace_data_out(debug_bus_mux), .coretrace_ctrls_in(coretrace_ctrls_in), .coretrace_ctrls_out(coretrace_ctrls_mux) ); //------------------------------------------------------------------------------------------------------------ // Latches //------------------------------------------------------------------------------------------------------------ assign trc_act = pc_rv_trace_bus_enable; assign evt_act = pc_rv_event_bus_enable; assign delay_lclkr = prv_delay_lclkr_dc[0]; assign mpw1_b = prv_mpw1_dc_b[0]; assign mpw2_b = prv_mpw2_dc_b; tri_rlmreg_p #(.WIDTH(32), .INIT(0)) debug_bus_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(trc_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[debug_bus_offset:debug_bus_offset + 32 - 1]), .scout(sov[debug_bus_offset:debug_bus_offset + 32 - 1]), .din(debug_bus_mux), .dout(debug_bus_out) ); tri_rlmreg_p #(.WIDTH(11), .INIT(0)) debug_mux_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(trc_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[debug_mux_offset:debug_mux_offset + 11 - 1]), .scout(sov[debug_mux_offset:debug_mux_offset + 11 - 1]), .din(pc_rv_debug_mux_ctrls), .dout(debug_mux_ctrls) ); tri_rlmreg_p #(.WIDTH(4*`THREADS), .INIT(0)) event_bus_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(evt_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[event_bus_offset:event_bus_offset + 4*`THREADS - 1]), .scout(sov[event_bus_offset:event_bus_offset + 4*`THREADS - 1]), .din(event_bus_d), .dout(event_bus_q) ); tri_rlmreg_p #(.WIDTH(3), .INIT(0)) event_count_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(evt_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[event_count_offset:event_count_offset + 3 - 1]), .scout(sov[event_count_offset:event_count_offset + 3 - 1]), .din(pc_rv_event_count_mode), .dout(event_count_mode) ); tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) spr_msr_gs_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(evt_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[spr_msr_gs_offset:spr_msr_gs_offset + `THREADS - 1]), .scout(sov[spr_msr_gs_offset:spr_msr_gs_offset + `THREADS - 1]), .din(spr_msr_gs), .dout(spr_msr_gs_q) ); tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0)) spr_msr_pr_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(evt_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[spr_msr_pr_offset:spr_msr_pr_offset + `THREADS - 1]), .scout(sov[spr_msr_pr_offset:spr_msr_pr_offset + `THREADS - 1]), .din(spr_msr_pr), .dout(spr_msr_pr_q) ); tri_rlmreg_p #(.WIDTH(40), .INIT(0)) event_mux_ctrls_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(evt_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[event_mux_ctrls_offset:event_mux_ctrls_offset + 40 - 1]), .scout(sov[event_mux_ctrls_offset:event_mux_ctrls_offset + 40 - 1]), .din(pc_rv_event_mux_ctrls), .dout(event_mux_ctrls) ); tri_rlmreg_p #(.WIDTH(4), .INIT(0)) core_trace_ctrls_reg( .vd(vdd), .gd(gnd), .nclk(nclk), .act(trc_act), .thold_b(func_sl_thold_0_b), .sg(sg_0), .force_t(force_t), .delay_lclkr(delay_lclkr), .mpw1_b(mpw1_b), .mpw2_b(mpw2_b), .d_mode(d_mode), .scin(siv[coretrace_ctrls_offset:coretrace_ctrls_offset + 4 - 1]), .scout(sov[coretrace_ctrls_offset:coretrace_ctrls_offset + 4 - 1]), .din(coretrace_ctrls_mux), .dout(coretrace_ctrls_out) ); //------------------------------------------------------------------------------------------------------------ // Scan Connections //------------------------------------------------------------------------------------------------------------ assign siv[0:scan_right-1] = {sov[1:scan_right-1], scan_in}; assign scan_out = sov[0]; endmodule