You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
14 KiB
Verilog

// © IBM Corp. 2022
// 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.
// A2L2 bridge
// 1. interface to a sim mem[]
// 2. interface to wb (could use mem for l2 also)
a2l2wb n0(
parameter MEM_QW = 16384;
)
(
input clk,
input rst,
input ac_an_req_pwr_token,
input ac_an_req,
input [64-`REAL_IFAR_WIDTH:63] ac_an_req_ra,
input [0:5] ac_an_req_ttype,
input [0:2] ac_an_req_thread,
input [0:4] ac_an_req_ld_core_tag,
input [0:2] ac_an_req_ld_xfr_len,
input ac_an_req_wimg_w,
input ac_an_req_wimg_i,
input ac_an_req_wimg_m,
input ac_an_req_wimg_g,
input ac_an_req_endian,
input [0:3] ac_an_req_user_defined,
input [0:3] ac_an_req_spare_ctrl_a0,
input ac_an_st_data_pwr_token,
input [0:31] ac_an_st_byte_enbl,
input [0:255] ac_an_st_data,
output an_ac_reld_data_vld,
output [0:4] an_ac_reld_core_tag,
output [0:127] an_ac_reld_data,
output [58:59] an_ac_reld_qw,
output an_ac_reld_ecc_err,
output an_ac_reld_ecc_err_ue,
output an_ac_reld_data_coming,
output an_ac_reld_ditc,
output an_ac_reld_crit_qw,
output an_ac_reld_l1_dump,
output [0:3] an_ac_req_spare_ctrl_a1,
output [0:`THREADS-1] an_ac_sync_ack,
output an_ac_req_ld_pop,
output an_ac_req_st_pop,
output an_ac_req_st_gather,
output [0:`THREADS-1] an_ac_stcx_complete,
output [0:`THREADS-1] an_ac_stcx_pass,
output [0:`THREADS-1] an_ac_reservation_vld,
output an_ac_icbi_ack,
output [0:1] an_ac_icbi_ack_thread,
output an_ac_back_inv,
output [64-`REAL_IFAR_WIDTH:63] an_ac_back_inv_addr,
output [0:4] an_ac_back_inv_target,
output an_ac_back_inv_local,
output an_ac_back_inv_lbit,
output an_ac_back_inv_gs,
output an_ac_back_inv_ind,
output [0:7] an_ac_back_inv_lpar_id,
input ac_an_back_inv_reject,
input [0:7] ac_an_lpar_id,
output [0:31] mem_adr,
input [0:127] mem_dat,
output mem_wr_val,
output [0:127] mem_wr_dat,
output wb_i_stb,
output wb_i_cyc,
output [31:0] wb_i_adr,
input wb_i_ack,
input [31:0] wb_i_datr,
output wb_d_stb,
output wb_d_cyc,
output [31:0] wb_d_adr,
output wb_d_we,
output [3:0] wb_d_sel,
output [31:0] wb_d_datw,
input wb_d_ack,
input [31:0] wb_d_datr
);
// unsupported right now
assign an_ac_sync_ack = 0;
assign an_ac_stcx_complete = 0;
assign an_ac_stcx_pass = 0;
assign an_ac_reservation_vld = 0;
assign an_ac_icbi_ack = 0;
assign an_ac_icbi_ack_thread = 0;
assign an_ac_back_inv = 0;
assign an_ac_back_inv_addr = 0;
assign an_ac_back_inv_target = 0;
assign an_ac_back_inv_local = 0;
assign an_ac_back_inv_lbit = 0;
assign an_ac_back_inv_gs = 0;
assign an_ac_back_inv_ind = 0;
assign an_ac_back_inv_lpar_id = 0;
assign an_ac_req_st_gather = 0;
assign an_ac_req_spare_ctrl_a1 = 0;
assign an_ac_reld_l1_dump = 0;
wire [0:4] cmdseq_d;
reg [0:4] cmdseq_q;
wire [0:31+`REAL_IFAR_WIDTH] req_d;
reg [0:31+`REAL_IFAR_WIDTH] req_q;
wire [0:31+256] std_d;
reg [0:31+256] std_q;
reg std_q
reg req_tkn_q;
reg std_tkn_q;
wire [0:255] rld_d;
reg [0:255] rld_q;
wire req_ld_val;
wire req_st_val;
wire [64-`REAL_IFAR_WIDTH:63] req_adr;
wire [0:127] st_alg_data;
wire [0:127] st_mask;
wire rld_coming;
wire rld_valid;
wire rld_done;
wire [0:1] rld_qw;
wire idle;
//reg [0:127] mem[MEM_QW];
// todo
/*
input ac_an_req_pwr_token,
input ac_an_req,
input [64-`REAL_IFAR_WIDTH:63] ac_an_req_ra,
input [0:5] ac_an_req_ttype,
input [0:2] ac_an_req_thread,
input [0:4] ac_an_req_ld_core_tag,
input [0:2] ac_an_req_ld_xfr_len,
input ac_an_req_wimg_w,
input ac_an_req_wimg_i,
input ac_an_req_wimg_m,
input ac_an_req_wimg_g,
input ac_an_req_endian,
input [0:3] ac_an_req_user_defined,
input [0:3] ac_an_req_spare_ctrl_a0,
input ac_an_st_data_pwr_token,
input [0:31] ac_an_st_byte_enbl,
input [0:255] ac_an_st_data
*/
// FF
always @(posedge clk) begin
if (rst) begin
cmdseq_q = 'b11111;
req_q = 0;
std_q = 0;
req_tkn_q = 0;
std_tkn_q = 0;
end else begin
cmdseq_q = cmdseq_d;
req_q = req_d;
std_q = std_d;
req_tkn_q = ac_an_req_pwr_token;
std_tkn_q = ac_an_st_data_pwr_token;
end
end
// Mem
/*
always @(posedge clk) begin
if (do_store) begin
mem[req_adr] = st_rmw_data;
end
end
assign mem_dat = mem[mem_adr];
*/
assign mem_adr = req_adr >> 4;
// clkgate
assign req_d = req_tkn_q ? {ac_an_req,
ac_an_req_thread, // 0:2
ac_an_req_ttype, // 0:5
ac_an_req_ld_core_tag, // 0:2
ac_an_req_ra, //
ac_an_req_ld_xfr_len, // 0:2
ac_an_req_wimg_w,
ac_an_req_wimg_i,
ac_an_req_wimg_m,
ac_an_req_wimg_g,
ac_an_req_wimg_endian,
ac_an_req_user_defined, // 0:3
ac_an_req_spare_ctrl_a0 // 0:3
} : 0;
assign std_d = std_tkn_q ? {ac_an_st_byte_enbl, // 0:31
ac_an_st_data // 0:255
} : 0;
// request
assign req_ld_val = req_q[0] & (
(req_q[4:9] == 'b000000) | // if
(req_q[4:9] == 'b001000) | // ld
(req_q[4:9] == 'b100010) | // ditc
(req_q[4:9] == 'b001001) | // larx
(req_q[4:9] == 'b001011); // larx hint
);
assign req_st_val = req_q[0] & (
(req_q[4:9] == 'b100000) | // st
(req_q[4:9] == 'b101001) // stcx
);
assign req_tag = req_q[10:12];
assign req_adr = req_q[14+64-`REAL_IFAR_WIDTH:14+63];
// coming --- ---
// valid --- --- --- --- (and qw, crit)
// data --- --- --- ---
//tbl cmdseq
//n cmdseq_q cmdseq_d
//n | | rld_coming
//n | ld_req_val | |rld_valid
//n | |st_req_val | ||do_store
//n | ||ld_ready | |||rld_done
//n | |||st_ready | ||||
//n | ||||ld_ieq1 | |||| idle
//n | ||||| | |||| |
//n | ||||| | |||| |
//b 01234 ||||| 01234 |||| |
//t iiiii iiiii ooooo oooo o
//*----------------------------------------------------------------------
//* Idle ****************************************************************
//s 11111 ----- ----- 0000 1
//s 11111 00--- 11111 0000 - * ...zzz...
//s 11111 1---- 00001 0000 -
//s 11111 -1--- 10000 0000 -
//* Load ****************************************************************
//* 00001 --0-- 00001 0000 0
//* 00001 --1-- 00010 1000 0
//* Reload V0 *********************************************************** * val 0
//* 00010 ----1 00011 0100 0
//* 00011 ----0 00100 0100 0
//* Reload D0 (I=1) ****************************************************** * dat 0
//* 00011 ----- 11111 0001 0
//* Reload D0 ************************************************************ * val 1, dat 0
//* 00100 ----- 00101 1100 0
//* Reload D1 ************************************************************ * val 2, dat 1
//* 00101 ----- 00110 0100 0
//* Reload D2 ************************************************************ * val 3, dat 2
//* 00110 ----- 00111 0100 0
//* Reload D3 ************************************************************ * dat 3
//* 00111 ----- 11111 0001 0
//* Store ***************************************************************
//* 10000 ---0- 10000 0000 0
//* 10000 ---1- 11111 0010 0
//*----------------------------------------------------------------------
//tbl cmdseq
assign reld_qw = cmdseq_q[3:4];
// response
assign an_ac_reld_ecc_err = 0;
assign an_ac_reld_ecc_err_ue = 0;
assign an_ac_reld_ditc = 0;
// loads
assign an_ac_reld_data_coming = rld_coming;
assign an_ac_reld_data_vld = rld_valid;
assign an_ac_reld_core_tag = req_tag;
assign an_ac_reld_qw = reld_qw;
assign an_ac_reld_crit_qw = req_ieq1 | (req_adr[58:59] == reld_qw);
assign an_ac_reld_data = mem[{req_adr[64-`REAL_IFAR_WIDTH:59], reld_qw}];
assign an_ac_req_ld_pop = rld_done;
// stores
assign st_ready = 1; // random delay, or future functional stuff
assign an_ac_req_st_pop = st_ready;
assign st_mask = {
{8{std_q[0]}}, {8{std_q[1]}}, {8{std_q[2]}}, {8{std_q[3]}},
{8{std_q[4]}}, {8{std_q[5]}}, {8{std_q[6]}}, {8{std_q[7]}},
{8{std_q[8]}}, {8{std_q[9]}}, {8{std_q[10]}}, {8{std_q[11]}},
{8{std_q[12]}}, {8{std_q[13]}}, {8{std_q[14]}}, {8{std_q[15]}},
{8{std_q[16]}}, {8{std_q[17]}}, {8{std_q[18]}}, {8{std_q[19]}},
{8{std_q[20]}}, {8{std_q[21]}}, {8{std_q[22]}}, {8{std_q[23]}},
{8{std_q[24]}}, {8{std_q[25]}}, {8{std_q[26]}}, {8{std_q[27]}},
{8{std_q[28]}}, {8{std_q[29]}}, {8{std_q[30]}}, {8{std_q[31]}}
};
// BE, 16B max store
assign st_alg_data = req_q[32:32+127]; // no shift needed?
assign mem_wr_val = do_store;
assign mem_wr_dat = (mem_dat & st_mask) | (st_alg_data & ~st_mask);
//vtable cmdseq
//vtable cmdseq