From 2790e84d19b746834e0c87b616df5769b1be8cd8 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Fri, 19 Aug 2022 12:04:36 +0200 Subject: [PATCH 01/19] rtl: add AXI4-Lite to Avalon-MM bridge Signed-off-by: Karol Budniak --- rtl/axil_avalon_mm.v | 275 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 rtl/axil_avalon_mm.v diff --git a/rtl/axil_avalon_mm.v b/rtl/axil_avalon_mm.v new file mode 100644 index 00000000..97fdd531 --- /dev/null +++ b/rtl/axil_avalon_mm.v @@ -0,0 +1,275 @@ +/* + +Copyright (c) 2022 Missing Link Electronics, Inc. + +Author: Karol Budniak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Description: The AXI4-Lite to Avalon-MM bridge implementation. + +Convert a single AXI4-Lite read/write transfer into Avalon-MM transfer +Avalon-MM specification taken from Intel Avalon Interface Specifications +version 683091 | 2022.01.24 + +Features not supported: +a) write/read burst +b) AXI4-Lite protection +c) Avalon-MM interface: 'lock' signal, pipelined read with + fixed and with variable latency, other than default properties +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +module axil_avalon_mm #( + parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32, + parameter STRB_WIDTH = (DATA_WIDTH/8), + parameter BYTEENABLE_WIDTH = (DATA_WIDTH/8) +) +( + input wire clk, + input wire rst, + + /* + * AXI lite slave interface + */ + input wire [ADDR_WIDTH-1:0] s_axil_awaddr, + input wire [2:0] s_axil_awprot, + input wire s_axil_awvalid, + output wire s_axil_awready, + input wire [DATA_WIDTH-1:0] s_axil_wdata, + input wire [STRB_WIDTH-1:0] s_axil_wstrb, + input wire s_axil_wvalid, + output wire s_axil_wready, + output wire [1:0] s_axil_bresp, + output wire s_axil_bvalid, + input wire s_axil_bready, + input wire [ADDR_WIDTH-1:0] s_axil_araddr, + input wire [2:0] s_axil_arprot, + input wire s_axil_arvalid, + output wire s_axil_arready, + output wire [DATA_WIDTH-1:0] s_axil_rdata, + output wire [1:0] s_axil_rresp, + output wire s_axil_rvalid, + input wire s_axil_rready, + + /* + * Avalon MM host interface + */ + output wire [ADDR_WIDTH-1:0] h_avalon_mm_address, + output wire [BYTEENABLE_WIDTH-1:0] h_avalon_mm_byteenable, + output wire h_avalon_mm_read, + input wire [DATA_WIDTH-1:0] h_avalon_mm_readdata, + input wire [1:0] h_avalon_mm_response, + output wire h_avalon_mm_write, + output wire [DATA_WIDTH-1:0] h_avalon_mm_writedata, + input wire h_avalon_mm_waitrequest +); + +reg s_axil_awready_reg = 1'b0; +reg s_axil_wready_reg = 1'b0; +reg [1:0] s_axil_bresp_reg; +reg s_axil_bvalid_reg = 1'b0; +reg s_axil_arready_reg = 1'b0; +reg [DATA_WIDTH-1:0] s_axil_rdata_reg; +reg [1:0] s_axil_rresp_reg; +reg s_axil_rvalid_reg = 1'b0; + +assign s_axil_awready = s_axil_awready_reg; +assign s_axil_wready = s_axil_wready_reg; +assign s_axil_bresp = s_axil_bresp_reg; +assign s_axil_bvalid = s_axil_bvalid_reg; +assign s_axil_arready = s_axil_arready_reg; +assign s_axil_rdata = s_axil_rdata_reg; +assign s_axil_rresp = s_axil_rresp_reg; +assign s_axil_rvalid = s_axil_rvalid_reg; + +reg [ADDR_WIDTH-1:0] h_avalon_mm_address_reg = 0; +reg [BYTEENABLE_WIDTH-1:0] h_avalon_mm_byteenable_reg = 0; +reg h_avalon_mm_read_reg = 1'b0; +reg h_avalon_mm_write_reg = 1'b0; +reg [DATA_WIDTH-1:0] h_avalon_mm_writedata_reg = 0; + +assign h_avalon_mm_address = h_avalon_mm_address_reg; +assign h_avalon_mm_byteenable = h_avalon_mm_byteenable_reg; +assign h_avalon_mm_read = h_avalon_mm_read_reg; +assign h_avalon_mm_write = h_avalon_mm_write_reg; +assign h_avalon_mm_writedata = h_avalon_mm_writedata_reg; + +localparam [2:0] + STATE_IDLE = 4'd0, + STATE_START_AVALON_WRITE = 4'd1, + STATE_START_AVALON_READ = 4'd2, + STATE_CHECK_AVALON_WAITREQUEST = 4'd3, + STATE_VALIDATE_AXI_BRESP = 4'd4, + STATE_WAIT_AXI_BREADY = 4'd5, + STATE_VALIDATE_AXI_RVALID = 4'd6, + STATE_WAIT_AXI_RREADY = 4'd7; + +reg [2:0] state_reg = STATE_IDLE; +reg [2:0] state_next; +reg rnw = 1'b0; +reg [ADDR_WIDTH-1:0] address; +reg [DATA_WIDTH-1:0] writedata; +reg [DATA_WIDTH-1:0] readdata; +reg [BYTEENABLE_WIDTH-1:0] byteenable; +reg [1:0] response; + +always @(posedge clk) begin + state_reg <= state_next; + if (rst) begin + state_reg <= STATE_IDLE; + end +end + +always @* begin + state_next = state_reg; + case (state_reg) + STATE_IDLE: begin + if (s_axil_awvalid && s_axil_awready && + s_axil_wvalid && s_axil_wready) + begin + state_next = STATE_START_AVALON_WRITE; + end else if (s_axil_arvalid && s_axil_arready) begin + state_next = STATE_START_AVALON_READ; + end + end + STATE_START_AVALON_WRITE, + STATE_START_AVALON_READ: begin + state_next = STATE_CHECK_AVALON_WAITREQUEST; + end + STATE_CHECK_AVALON_WAITREQUEST: begin + if (!h_avalon_mm_waitrequest) begin + if (rnw) begin + state_next = STATE_VALIDATE_AXI_RVALID; + end else begin + state_next = STATE_VALIDATE_AXI_BRESP; + end + end + end + STATE_VALIDATE_AXI_BRESP: begin + state_next = STATE_WAIT_AXI_BREADY; + end + STATE_WAIT_AXI_BREADY: begin + if (s_axil_bready) begin + state_next = STATE_IDLE; + end + end + STATE_VALIDATE_AXI_RVALID: begin + state_next = STATE_WAIT_AXI_RREADY; + end + STATE_WAIT_AXI_RREADY: begin + if (s_axil_rready) begin + state_next = STATE_IDLE; + end + end + default: begin + state_next = STATE_IDLE; + end + endcase +end + +always @(posedge clk) begin + s_axil_awready_reg <= 1'b0; + s_axil_wready_reg <= 1'b0; + s_axil_arready_reg <= 1'b0; + + case (state_reg) + STATE_IDLE: begin + if (s_axil_awvalid && !s_axil_awready && + s_axil_wvalid && !s_axil_wready) + begin + s_axil_awready_reg <= 1'b1; + s_axil_wready_reg <= 1'b1; + address <= s_axil_awaddr; + writedata <= s_axil_wdata; + byteenable <= s_axil_wstrb; + end else if (s_axil_arvalid && !s_axil_arready) begin + s_axil_arready_reg <= 1'b1; + address <= s_axil_araddr; + end + end + STATE_START_AVALON_WRITE: begin + h_avalon_mm_address_reg <= address; + h_avalon_mm_byteenable_reg <= byteenable; + h_avalon_mm_writedata_reg <= writedata; + h_avalon_mm_write_reg <= 1'b1; + rnw <= 1'b0; + end + STATE_START_AVALON_READ: begin + h_avalon_mm_address_reg <= address; + h_avalon_mm_byteenable_reg <= byteenable; + h_avalon_mm_read_reg <= 1'b1; + rnw <= 1'b1; + end + STATE_CHECK_AVALON_WAITREQUEST: begin + if (!h_avalon_mm_waitrequest) begin + h_avalon_mm_write_reg <= 1'b0; + h_avalon_mm_read_reg <= 1'b0; + // capture read data also in case of write transfer + // it will not be used but makes will simplify logic + readdata <= h_avalon_mm_readdata; + // response encoding is the same for AXI4-Lite and Avalon-MM + // according to specification Intel Avalon Interface + // Specifications 683091 | 2022.01.24 + // chapter 3.2 Avalon Memory Mapped Interface Signal Roles + response <= h_avalon_mm_response; + end + end + STATE_VALIDATE_AXI_BRESP: begin + s_axil_bresp_reg <= response; + s_axil_bvalid_reg <= 1'b1; + end + STATE_WAIT_AXI_BREADY: begin + if (s_axil_bready) begin + s_axil_bvalid_reg <= 1'b0; + end + end + STATE_VALIDATE_AXI_RVALID: begin + s_axil_rdata_reg <= readdata; + s_axil_rresp_reg <= response; + s_axil_rvalid_reg <= 1'b1; + end + STATE_WAIT_AXI_RREADY: begin + if (s_axil_rready) begin + s_axil_rvalid_reg <= 1'b0; + end + end + default: begin + s_axil_bvalid_reg <= 1'b0; + s_axil_rvalid_reg <= 1'b0; + h_avalon_mm_write_reg <= 1'b0; + h_avalon_mm_read_reg <= 1'b0; + end + endcase + + if (rst) begin + s_axil_bvalid_reg <= 1'b0; + s_axil_rvalid_reg <= 1'b0; + h_avalon_mm_write_reg <= 1'b0; + h_avalon_mm_read_reg <= 1'b0; + end +end + +endmodule + From 2b743dfa32c862d5c20537d4e27403ac768a74e8 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Tue, 27 Sep 2022 20:23:13 +0200 Subject: [PATCH 02/19] rtl: add Avalon-MM address conversion module needed for Intel L-Tile/H-Tile Transceiver PHY reconfiguration interface Signed-off-by: Karol Budniak --- rtl/avalon_mm_addr_conv.v | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 rtl/avalon_mm_addr_conv.v diff --git a/rtl/avalon_mm_addr_conv.v b/rtl/avalon_mm_addr_conv.v new file mode 100644 index 00000000..79e18c42 --- /dev/null +++ b/rtl/avalon_mm_addr_conv.v @@ -0,0 +1,93 @@ +/* + +Copyright (c) 2022 Missing Link Electronics, Inc. + +Author: Karol Budniak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Description: This module implements a conversion from (double-word aligned) +Byte-Addressing (the two LSBs are always zero) to Word-Addressing by removing +the two LSBs and optionally expanding the MSBs with zero, if required to +satisfy the requested target address width. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +module avalon_mm_addr_conv #( + /* + * The only one tested use case is ADDR_WIDTH = 32 + * not all widths are supported neither have not been + * tested however may work as well + */ + parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32, + parameter BYTEENABLE_WIDTH = (DATA_WIDTH/8) +) +( + /* + * Avalon MM in interface + */ + input wire [ADDR_WIDTH-1:0] avalon_mm_in_address, + input wire [BYTEENABLE_WIDTH-1:0] avalon_mm_in_byteenable, + input wire avalon_mm_in_read, + output wire [DATA_WIDTH-1:0] avalon_mm_in_readdata, + output wire [1:0] avalon_mm_in_response, + input wire avalon_mm_in_write, + input wire [DATA_WIDTH-1:0] avalon_mm_in_writedata, + output wire avalon_mm_in_waitrequest, + + /* + * Avalon MM out interface + */ + output wire [ADDR_WIDTH-1:0] avalon_mm_out_address, + output wire [BYTEENABLE_WIDTH-1:0] avalon_mm_out_byteenable, + output wire avalon_mm_out_read, + input wire [DATA_WIDTH-1:0] avalon_mm_out_readdata, + input wire [1:0] avalon_mm_out_response, + output wire avalon_mm_out_write, + output wire [DATA_WIDTH-1:0] avalon_mm_out_writedata, + input wire avalon_mm_out_waitrequest +); + +// bus width assertions +initial begin + if (ADDR_WIDTH < 4) begin + $error("Error: Avalon-MM address width smaller than 4, this is not supported"); + $finish; + end +end + +/* + * double word address becomes byte address + */ +assign avalon_mm_out_address = {2'b00, avalon_mm_in_address[ADDR_WIDTH-1:2]}; +assign avalon_mm_out_byteenable = avalon_mm_in_byteenable; +assign avalon_mm_out_read = avalon_mm_in_read; +assign avalon_mm_in_readdata = avalon_mm_out_readdata; +assign avalon_mm_in_response = avalon_mm_out_response; +assign avalon_mm_out_write = avalon_mm_in_write; +assign avalon_mm_out_writedata = avalon_mm_in_writedata; +assign avalon_mm_in_waitrequest = avalon_mm_out_waitrequest; + +endmodule + From 58cf5eb53c5597031b985430ab9bb55f2d51c0f1 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Mon, 24 Oct 2022 14:38:19 +0200 Subject: [PATCH 03/19] rtl: add xfcp_mod_avmm.v Signed-off-by: Karol Budniak --- rtl/xfcp_mod_avmm.v | 237 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 rtl/xfcp_mod_avmm.v diff --git a/rtl/xfcp_mod_avmm.v b/rtl/xfcp_mod_avmm.v new file mode 100644 index 00000000..62d1d12d --- /dev/null +++ b/rtl/xfcp_mod_avmm.v @@ -0,0 +1,237 @@ +/* + +Copyright (c) 2022 Missing Link Electronics, Inc. + +Author: Karol Budniak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Description: The XFCP Avalon-MM wrapper with XFCP to AXI4-Lite converter +AXI4-Lite to Avalon-MM converter and Avalon-MM address converter instances + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +module xfcp_mod_avmm # +( + parameter XFCP_ID_TYPE = 16'h0001, + parameter XFCP_ID_STR = "AXIL Master", + /* + * The only one tested use case is ADDR_WIDTH = 32 + * not all widths are supported neither have not been + * tested however may work as well + */ + parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32, + parameter STRB_WIDTH = (DATA_WIDTH/8), + parameter BYTEENABLE_WIDTH = (DATA_WIDTH/8), + parameter USE_ADDR_CONVERTER = 0 +) +( + input wire clk, + input wire rst, + + /* + * XFCP upstream interface + */ + input wire [7:0] up_xfcp_in_tdata, + input wire up_xfcp_in_tvalid, + output wire up_xfcp_in_tready, + input wire up_xfcp_in_tlast, + input wire up_xfcp_in_tuser, + + output wire [7:0] up_xfcp_out_tdata, + output wire up_xfcp_out_tvalid, + input wire up_xfcp_out_tready, + output wire up_xfcp_out_tlast, + output wire up_xfcp_out_tuser, + + /* + * Avalon MM host interface + */ + output wire [ADDR_WIDTH-1:0] h_avalon_mm_address, + output wire [BYTEENABLE_WIDTH-1:0] h_avalon_mm_byteenable, + output wire h_avalon_mm_read, + input wire [DATA_WIDTH-1:0] h_avalon_mm_readdata, + input wire [1:0] h_avalon_mm_response, + output wire h_avalon_mm_write, + output wire [DATA_WIDTH-1:0] h_avalon_mm_writedata, + input wire h_avalon_mm_waitrequest +); + +/* + * AXI4-Lite internal interface + */ +wire [ADDR_WIDTH-1:0] axil_awaddr; +wire [2:0] axil_awprot; +wire axil_awvalid; +wire axil_awready; +wire [DATA_WIDTH-1:0] axil_wdata; +wire [STRB_WIDTH-1:0] axil_wstrb; +wire axil_wvalid; +wire axil_wready; +wire [1:0] axil_bresp; +wire axil_bvalid; +wire axil_bready; +wire [ADDR_WIDTH-1:0] axil_araddr; +wire [2:0] axil_arprot; +wire axil_arvalid; +wire axil_arready; +wire [DATA_WIDTH-1:0] axil_rdata; +wire [1:0] axil_rresp; +wire axil_rvalid; +wire axil_rready; + + +/* + * Avalon MM internal interface + */ +wire [ADDR_WIDTH-1:0] avalon_mm_address; +wire [BYTEENABLE_WIDTH-1:0] avalon_mm_byteenable; +wire avalon_mm_read; +wire [DATA_WIDTH-1:0] avalon_mm_readdata; +wire [1:0] avalon_mm_response; +wire avalon_mm_write; +wire [DATA_WIDTH-1:0] avalon_mm_writedata; +wire avalon_mm_waitrequest; + +xfcp_mod_axil #( + .XFCP_ID_TYPE(XFCP_ID_TYPE), + .XFCP_ID_STR(XFCP_ID_STR), + .DATA_WIDTH(DATA_WIDTH), + .ADDR_WIDTH(ADDR_WIDTH) +) +xfcp_mod_axil_inst ( + .clk(clk), + .rst(rst), + .up_xfcp_in_tdata(up_xfcp_in_tdata), + .up_xfcp_in_tvalid(up_xfcp_in_tvalid), + .up_xfcp_in_tready(up_xfcp_in_tready), + .up_xfcp_in_tlast(up_xfcp_in_tlast), + .up_xfcp_in_tuser(up_xfcp_in_tuser), + .up_xfcp_out_tdata(up_xfcp_out_tdata), + .up_xfcp_out_tvalid(up_xfcp_out_tvalid), + .up_xfcp_out_tready(up_xfcp_out_tready), + .up_xfcp_out_tlast(up_xfcp_out_tlast), + .up_xfcp_out_tuser(up_xfcp_out_tuser), + .m_axil_awaddr(axil_awaddr), + .m_axil_awprot(axil_awprot), + .m_axil_awvalid(axil_awvalid), + .m_axil_awready(axil_awready), + .m_axil_wdata(axil_wdata), + .m_axil_wstrb(axil_wstrb), + .m_axil_wvalid(axil_wvalid), + .m_axil_wready(axil_wready), + .m_axil_bresp(axil_bresp), + .m_axil_bvalid(axil_bvalid), + .m_axil_bready(axil_bready), + .m_axil_araddr(axil_araddr), + .m_axil_arprot(axil_arprot), + .m_axil_arvalid(axil_arvalid), + .m_axil_arready(axil_arready), + .m_axil_rdata(axil_rdata), + .m_axil_rresp(axil_rresp), + .m_axil_rvalid(axil_rvalid), + .m_axil_rready(axil_rready) +); + + +axil_avalon_mm #( + .ADDR_WIDTH(ADDR_WIDTH), + .DATA_WIDTH(DATA_WIDTH) +) +axil_avalon_mm_inst ( + .clk(clk), + .rst(rst), + + .s_axil_awaddr(axil_awaddr), + .s_axil_awprot(axil_awprot), + .s_axil_awvalid(axil_awvalid), + .s_axil_awready(axil_awready), + .s_axil_wdata(axil_wdata), + .s_axil_wstrb(axil_wstrb), + .s_axil_wvalid(axil_wvalid), + .s_axil_wready(axil_wready), + .s_axil_bresp(axil_bresp), + .s_axil_bvalid(axil_bvalid), + .s_axil_bready(axil_bready), + .s_axil_araddr(axil_araddr), + .s_axil_arprot(axil_arprot), + .s_axil_arvalid(axil_arvalid), + .s_axil_arready(axil_arready), + .s_axil_rdata(axil_rdata), + .s_axil_rresp(axil_rresp), + .s_axil_rvalid(axil_rvalid), + .s_axil_rready(axil_rready), + + + .h_avalon_mm_address(avalon_mm_address), + .h_avalon_mm_byteenable(avalon_mm_byteenable), + .h_avalon_mm_read(avalon_mm_read), + .h_avalon_mm_readdata(avalon_mm_readdata), + .h_avalon_mm_response(avalon_mm_response), + .h_avalon_mm_write(avalon_mm_write), + .h_avalon_mm_writedata(avalon_mm_writedata), + .h_avalon_mm_waitrequest(avalon_mm_waitrequest) +); + +generate +if (USE_ADDR_CONVERTER) begin + + avalon_mm_addr_conv #( + .ADDR_WIDTH(ADDR_WIDTH), + .DATA_WIDTH(DATA_WIDTH) + ) + avalon_mm_addr_conv_inst ( + .avalon_mm_in_address(avalon_mm_address), + .avalon_mm_in_byteenable(avalon_mm_byteenable), + .avalon_mm_in_read(avalon_mm_read), + .avalon_mm_in_readdata(avalon_mm_readdata), + .avalon_mm_in_response(avalon_mm_response), + .avalon_mm_in_write(avalon_mm_write), + .avalon_mm_in_writedata(avalon_mm_writedata), + .avalon_mm_in_waitrequest(avalon_mm_waitrequest), + + .avalon_mm_out_address(h_avalon_mm_address), + .avalon_mm_out_byteenable(h_avalon_mm_byteenable), + .avalon_mm_out_read(h_avalon_mm_read), + .avalon_mm_out_readdata(h_avalon_mm_readdata), + .avalon_mm_out_response(h_avalon_mm_response), + .avalon_mm_out_write(h_avalon_mm_write), + .avalon_mm_out_writedata(h_avalon_mm_writedata), + .avalon_mm_out_waitrequest(h_avalon_mm_waitrequest) + ); +end else begin + + assign h_avalon_mm_address = avalon_mm_address; + assign h_avalon_mm_byteenable = avalon_mm_byteenable; + assign h_avalon_mm_read = avalon_mm_read; + assign avalon_mm_readdata = h_avalon_mm_readdata; + assign avalon_mm_response = h_avalon_mm_response; + assign h_avalon_mm_write = avalon_mm_write; + assign h_avalon_mm_writedata = avalon_mm_writedata; + assign avalon_mm_waitrequest = h_avalon_mm_waitrequest; +end + +endgenerate + +endmodule From 440bbd4c8913bf26fa8352c329db7d36ed0a45fa Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Wed, 31 Aug 2022 14:44:16 +0200 Subject: [PATCH 04/19] python/xfcp: add ltile_htile_node.py with first helper functions to access transceiver regs and do misc operations Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 345 ++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 python/xfcp/ltile_htile_node.py diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py new file mode 100644 index 00000000..fa6e9b33 --- /dev/null +++ b/python/xfcp/ltile_htile_node.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2022 Karol Budniak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +""" + +from . import node + +DBG_PRINT = False + +# register offsets taken from Intel document: +# L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 +# chapter A. Logical View of the L-Tile/H-Tile Transceiver Registers +# pages 480-504 + +PRBS_MODE_OFF = 0b00000 +PRBS_MODE_PRBS7 = 0b00001 +PRBS_MODE_PRBS9 = 0b00010 +PRBS_MODE_PRBS15 = 0b00100 +PRBS_MODE_PRBS23 = 0b01000 +PRBS_MODE_PRBS31 = 0b10000 + +prbs_mode_mapping = { + 'off': PRBS_MODE_OFF, + 'prbs7': PRBS_MODE_PRBS7, + 'prbs9': PRBS_MODE_PRBS9, + 'prbs15': PRBS_MODE_PRBS15, + 'prbs23': PRBS_MODE_PRBS23, + 'prbs31': PRBS_MODE_PRBS31 +} + +class LTileHTileNode(node.MemoryNode): + # expected byte address + def masked_read(self, addr, mask): + # multiple byte address by 4 so it does not get + # truncated because of 32 bit access of AXI4-Lite (converted to Avalon-MM) + val = self.read_word(addr << 2) & mask + if (DBG_PRINT): + print("TRACE: masked_read: address: " + str(hex(addr)) + ", mask: " + str(hex(mask)) + ", data: " + str(hex(val))) + return val + + # expected byte address + def masked_write(self, addr, mask, val): + if (DBG_PRINT): + print("TRACE: masked_write: address: " + str(hex(addr)) + ", mask: " + str(hex(mask) + ", data: " + str(hex(val)))) + # multiple byte address by 4 so it does not get + # truncated because of 32 bit access of AXI4-Lite (converted to Avalon-MM) + return self.write_word(addr << 2, (self.read_word(addr << 2) & ~mask) | (val & mask)) + + def dump_reg_space(self, start, stop): + for addr in range(start, stop, 0x001): + print("Address: " + str(hex(addr)) + ": " + str(hex(self.masked_read(addr, 0xFF)))) + + # return True if the receiver is locked to data + def get_rx_locked_to_data(self): + if (DBG_PRINT): + print("TRACE: get_rx_locked_to_data") + return bool(self.masked_read(0x480, 0x0001)) + + # return True if the receiver is locked to reference clock + def get_rx_locked_to_ref(self): + if (DBG_PRINT): + print("TRACE: get_rx_locked_to_ref") + return bool(self.masked_read(0x480, 0x0002)) + + # steps to follow to view Eyescan may also apply to run BER measurement + # presented in documentation L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 + # on pages 161 - 162 + def disable_background_calibration(self): + if (DBG_PRINT): + print("TRACE: disable_background_calibration") + self.masked_write(0x542, 0x01, 0x00) + + def is_avmm_bus_busy(self): + # return True if PreSICE has control of the internal configuration bus + # return False if you have control of internal configuration bus + if (DBG_PRINT): + print("TRACE: is_avmm_bus_busy") + return bool(self.masked_read(0x481, 0x04)) + + def is_rx_adaption_mode_manual(self): + # return True if RX adaptation is in manual mode, return False otherwise + if (DBG_PRINT): + print("TRACE: is_rx_adaption_mode_manual") + return bool(self.masked_read(0x161, 0x20)) + + def release_adaptation_from_reset(self): + if (DBG_PRINT): + print("TRACE: release_adaptation_from_reset") + self.masked_write(0x148, 0x01, 0x01) + + def enable_cnt_to_detect_error_bits(self): + if (DBG_PRINT): + print("TRACE: enable_cnt_to_detect_error_bits") + self.masked_write(0x169, 0x40, 0x01) + + def enable_serial_bit_checker(self): + if (DBG_PRINT): + print("TRACE: enable_serial_bit_checker") + self.masked_write(0x168, 0x01, 0x01) + + def is_dfe_enabled(self): + # return True if DFE is enabled, return False otherwise + if (DBG_PRINT): + print("TRACE: is_dfe_enabled") + return True if (self.masked_read(0x161, 0x40) == 0) else False + + def enable_dfe_speculation(self): + if (DBG_PRINT): + print("TRACE: enable_dfe_speculation") + self.masked_write(0x169, 0x04, 0x04) + + def disable_dfe_speculation(self): + if (DBG_PRINT): + print("TRACE: disable_dfe_speculation") + self.masked_write(0x169, 0x04, 0x00) + + def enable_serial_bit_checker_control(self): + if (DBG_PRINT): + print("TRACE: enable_serial_bit_checker_control") + self.masked_write(0x158, 0x20, 0x20) + + # PRBS Generator registers + def get_prbs_gen_prbs_tx_pma_data_sel(self): + if (DBG_PRINT): + print("TRACE: get_prbs_gen_prbs_tx_pma_data_sel") + # bits[4:3] from 0x008[6:5] + msb = self.masked_read(0x008, 0b1100000) >> 5 + # bits[2:0] from 0x006[2:0] + lsb = self.masked_read(0x006, 0b00111) >> 0 + val = (msb << 3) + lsb + return val + + def set_prbs_gen_prbs_tx_pma_data_sel(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_gen_prbs_tx_pma_data_sel") + # bits[4:3] to 0x008[6:5] + self.masked_write(0x008, 0b1100000, (val & 0b11000) << 2) + # bits[2:0] to 0x006[2:0] + self.masked_write(0x006, 0b00111, val & 0b00111) + + def get_prbs_gen_prbs9_dwidth(self): + if (DBG_PRINT): + print("TRACE: get_prbs_gen_prbs9_dwidth") + return bool(self.masked_read(0x006, 0x0008)) + + def set_prbs_gen_prbs9_dwidth(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_gen_prbs9_dwidth") + self.masked_write(0x006, 0x0008, 0x0008 if val else 0x0000) + + def get_prbs_gen_prbs_clken(self): + if (DBG_PRINT): + print("TRACE: get_prbs_gen_prbs_clken") + return bool(self.masked_read(0x006, 0x0040)) + + def set_prbs_gen_prbs_clken(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_gen_prbs_clken") + self.masked_write(0x006, 0x0040, 0x0040 if val else 0x0000) + + def get_prbs_gen_prbs_pat(self): + if (DBG_PRINT): + print("TRACE: get_prbs_gen_prbs_pat") + # bit[4] from 0x008[4] + msb = self.masked_read(0x008, 0x0010) + # bits[3:0] from 0x007[7:4] + lsb = self.masked_read(0x007, 0x00F0) >> 4 + val = msb + lsb + return val + + def set_prbs_gen_prbs_pat(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_gen_prbs_pat") + if type(val) is str: + val = prbs_mode_mapping[val] + # bit[4] to 0x008[4] + self.masked_write(0x008, 0x0010, val & 0x0010) + # bits[3:0] to 0x007[7:4] + self.masked_write(0x007, 0x00F0, (val & 0x000F) << 4) + + def get_prbs_gen_ser_mode(self): + if (DBG_PRINT): + print("TRACE: get_prbs_gen_ser_mode") + return (self.masked_read(0x110, 0x0007)) + + def set_prbs_gen_ser_mode(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_gen_ser_mode") + self.masked_write(0x110, 0x0007, val & 0x0007) + + # PRBS Verifier registers + def get_prbs_ver_prbs_clken(self): + if (DBG_PRINT): + print("TRACE: get_prbs_ver_prbs_clken") + return bool(self.masked_read(0x00A, 0x0080)) + + def set_prbs_ver_prbs_clken(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_ver_prbs_clken") + self.masked_write(0x00A, 0x0080, 0x0080 if val else 0x0000) + + def get_prbs_ver_rx_prbs_mask(self): + if (DBG_PRINT): + print("TRACE: get_prbs_ver_rx_prbs_mask") + return (self.masked_read(0x00B, 0x000C) >> 2) + + def set_prbs_ver_rx_prbs_mask(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_ver_rx_prbs_mask") + self.masked_write(0x00B, 0x000C, val << 2) + + def get_prbs_ver_prbs_pat(self): + if (DBG_PRINT): + print("TRACE: get_prbs_ver_prbs_pat") + # bit[4] from 0x00C[0] + msb = self.masked_read(0x00C, 0x0001) + # bits[3:0] from 0x00B[7:4] + lsb = self.masked_read(0x00B, 0x00F0) >> 4 + val = (msb << 4) + lsb + return val + + def set_prbs_ver_prbs_pat(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_ver_prbs_pat") + if type(val) is str: + val = prbs_mode_mapping[val] + # bit[4] to 0x00C[0] + self.masked_write(0x00C, 0x0001, (val & 0x0010) >> 4) + # bits[3:0] to 0x00B[7:4] + self.masked_write(0x00B, 0x00F0, (val & 0x000F) << 4) + + def get_prbs_ver_prbs9_dwidth(self): + if (DBG_PRINT): + print("TRACE: get_prbs_ver_prbs9_dwidth") + return bool(self.masked_read(0x00C, 0x0008)) + + def set_prbs_ver_prbs9_dwidth(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_ver_prbs9_dwidth") + self.masked_write(0x00C, 0x0008, 0x0008 if val else 0x0000) + + def get_prbs_ver_deser_factor(self): + if (DBG_PRINT): + print("TRACE: get_prbs_ver_deser_factor") + return (self.masked_read(0x13F, 0x000F)) + + def set_prbs_ver_deser_factor(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_ver_deser_factor") + self.masked_write(0x13F, 0x000F, val & 0x000F) + + # PRBS Soft Accumulators registers + def get_prbs_soft_acc_prbs_counter_en(self): + if (DBG_PRINT): + print("TRACE: get_prbs_soft_acc_prbs_counter_en") + return bool(self.masked_read(0x500, 0x0001)) + + def set_prbs_soft_acc_prbs_counter_en(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_soft_acc_prbs_counter_en") + self.masked_write(0x500, 0x0001, 0x0001 if val else 0x0000) + + def get_prbs_soft_acc_prbs_reset(self): + if (DBG_PRINT): + print("TRACE: get_prbs_soft_acc_prbs_reset") + return bool(self.masked_read(0x500, 0x0002)) + + def set_prbs_soft_acc_prbs_reset(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_soft_acc_prbs_reset") + self.masked_write(0x500, 0x0002, 0x0002 if val else 0x0000) + + def get_prbs_soft_acc_prbs_snap(self): + if (DBG_PRINT): + print("TRACE: get_prbs_soft_acc_prbs_snap") + return bool(self.masked_read(0x500, 0x0004)) + + def set_prbs_soft_acc_prbs_snap(self, val): + if (DBG_PRINT): + print("TRACE: set_prbs_soft_acc_prbs_snap") + self.masked_write(0x500, 0x0004, 0x0004 if val else 0x0000) + + def get_prbs_soft_acc_prbs_done(self): + if (DBG_PRINT): + print("TRACE: get_prbs_soft_acc_prbs_done") + return bool(self.masked_read(0x500, 0x0008)) + + def get_prbs_soft_acc_prbs_acc_err_cnt(self): + if (DBG_PRINT): + print("TRACE: get_prbs_soft_acc_prbs_acc_err_cnt") + val = 0 + move_iter = 0 + # accumulated error count under addresses 0x507 - 0x501 + for addr in range(0x501, 0x508): + # use only two bits from the most significant byte + if (addr == 0x507): + mask = 0x0003 + else: + mask = 0x00FF + read = self.masked_read(addr, mask) + # move each byte (8 * byte indicator) bits to the right + val += read << (move_iter * 8) + move_iter += 1 + return val + + def get_prbs_soft_acc_prbs_acc_bit_cnt(self): + if (DBG_PRINT): + print("TRACE: get_prbs_soft_acc_prbs_acc_bit_cnt") + val = 0 + move_iter = 0 + # accumulated bit count under addresses 0x513 - 0x50D + for addr in range(0x50D, 0x514): + # use only two bits from the most significant byte + if (addr == 0x513): + mask = 0x0003 + else: + mask = 0x00FF + read = self.masked_read(addr, mask) + # move each byte (8 * byte indicator) bits to the right + val += read << (move_iter * 8) + move_iter += 1 + return val + +node.register(LTileHTileNode, 0x9A83) + From 7239e4fe6a44c1f1e2d9c2735482f95a54eb3975 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Mon, 24 Oct 2022 20:12:13 +0200 Subject: [PATCH 05/19] python/xfcp/ltile_htile_node.py: add check for parameters before write on specific transceiver reconfiguration registers Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 94 +++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index fa6e9b33..9cf3aef1 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -27,6 +27,13 @@ DBG_PRINT = False +PRINT_VERBOSITY_TRACE = 4 +PRINT_VERBOSITY_INFO = 3 +PRINT_VERBOSITY_WARN = 2 +PRINT_VERBOSITY_ERROR = 1 +PRINT_VERBOSITY_QUIET = 0 +PRINT_VERBOSITY = PRINT_VERBOSITY_INFO + # register offsets taken from Intel document: # L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 # chapter A. Logical View of the L-Tile/H-Tile Transceiver Registers @@ -48,6 +55,28 @@ 'prbs31': PRBS_MODE_PRBS31 } +PRBS_GENERATOR_TX_PMA_DATA_SEL_SQUARE_WAVE = 0b00101 +PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN = 0b00100 + +PRBS_GENERATOR_PRBS9_DWIDTH_ENABLE = 0b1 +PRBS_GENERATOR_PRBS9_DWIDTH_DISABLE = 0b0 + +PRBS_GENERATOR_SERIALIZER_MODE_64BIT = 0b011 +PRBS_GENERATOR_SERIALIZER_MODE_10BIT = 0b100 + +prbs_generator_serializer_mode_mapping = { + 64: PRBS_GENERATOR_SERIALIZER_MODE_64BIT, + 10: PRBS_GENERATOR_SERIALIZER_MODE_10BIT +} + +PRBS_VERIFIER_DESERIALIZER_FACTOR_64BIT = 0xE +PRBS_VERIFIER_DESERIALIZER_FACTOR_10BIT = 0x1 + +prbs_verifier_deserializer_factor_mapping = { + 64: PRBS_VERIFIER_DESERIALIZER_FACTOR_64BIT, + 10: PRBS_VERIFIER_DESERIALIZER_FACTOR_10BIT +} + class LTileHTileNode(node.MemoryNode): # expected byte address def masked_read(self, addr, mask): @@ -151,8 +180,13 @@ def get_prbs_gen_prbs_tx_pma_data_sel(self): return val def set_prbs_gen_prbs_tx_pma_data_sel(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs_tx_pma_data_sel") + if ((val != PRBS_GENERATOR_TX_PMA_DATA_SEL_SQUARE_WAVE) and \ + (val != PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN)): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_gen_prbs_tx_pma_data_sel: unsupport TX PMA data selected: " + str(hex(val))) + exit(1) # bits[4:3] to 0x008[6:5] self.masked_write(0x008, 0b1100000, (val & 0b11000) << 2) # bits[2:0] to 0x006[2:0] @@ -189,10 +223,24 @@ def get_prbs_gen_prbs_pat(self): return val def set_prbs_gen_prbs_pat(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs_pat") + # check if argument is a string and map it to register value if type(val) is str: val = prbs_mode_mapping[val] + else: + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_gen_prbs_pat: argument given is not a string") + exit(1) + if ((val != PRBS_MODE_OFF) and \ + (val != PRBS_MODE_PRBS7) and \ + (val != PRBS_MODE_PRBS9) and \ + (val != PRBS_MODE_PRBS15) and \ + (val != PRBS_MODE_PRBS23) and \ + (val != PRBS_MODE_PRBS31)): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_gen_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) + exit(1) # bit[4] to 0x008[4] self.masked_write(0x008, 0x0010, val & 0x0010) # bits[3:0] to 0x007[7:4] @@ -204,8 +252,19 @@ def get_prbs_gen_ser_mode(self): return (self.masked_read(0x110, 0x0007)) def set_prbs_gen_ser_mode(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_ser_mode") + if type(val) is int: + val = prbs_generator_serializer_mode_mapping[val] + else: + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_gen_ser_mode: argument given is not an integer") + exit(1) + if ((val != PRBS_GENERATOR_SERIALIZER_MODE_64BIT) and + (val != PRBS_GENERATOR_SERIALIZER_MODE_10BIT)): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_gen_ser_mode: unsupported PRBS generator serializer mode: " + str(hex(val))) + exit(1) self.masked_write(0x110, 0x0007, val & 0x0007) # PRBS Verifier registers @@ -240,10 +299,24 @@ def get_prbs_ver_prbs_pat(self): return val def set_prbs_ver_prbs_pat(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_prbs_pat") + # check if argument is a string and map it to register value if type(val) is str: val = prbs_mode_mapping[val] + else: + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_ver_prbs_pat: argument given is not a string") + exit(1) + if ((val != PRBS_MODE_OFF) and \ + (val != PRBS_MODE_PRBS7) and \ + (val != PRBS_MODE_PRBS9) and \ + (val != PRBS_MODE_PRBS15) and \ + (val != PRBS_MODE_PRBS23) and \ + (val != PRBS_MODE_PRBS31)): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_ver_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) + exit(1) # bit[4] to 0x00C[0] self.masked_write(0x00C, 0x0001, (val & 0x0010) >> 4) # bits[3:0] to 0x00B[7:4] @@ -265,8 +338,19 @@ def get_prbs_ver_deser_factor(self): return (self.masked_read(0x13F, 0x000F)) def set_prbs_ver_deser_factor(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_deser_factor") + if type(val) is int: + val = prbs_verifier_deserializer_factor_mapping[val] + else: + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_ver_deser_factor: argument given is not an integer") + exit(1) + if ((val != PRBS_VERIFIER_DESERIALIZER_FACTOR_64BIT) and + (val != PRBS_VERIFIER_DESERIALIZER_FACTOR_10BIT)): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_ver_deser_factor: unsupported PRBS verifier deserializer factor: " + str(hex(val))) + exit(1) self.masked_write(0x13F, 0x000F, val & 0x000F) # PRBS Soft Accumulators registers From 636a94b4fbfa3e2a24582baec09c9cc19087a767 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Tue, 25 Oct 2022 18:38:17 +0200 Subject: [PATCH 06/19] python/xfcp/ltile_htile_node.py: fix prints Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 77 ++++++++++++++++----------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index 9cf3aef1..f834d8f3 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -25,7 +25,6 @@ from . import node -DBG_PRINT = False PRINT_VERBOSITY_TRACE = 4 PRINT_VERBOSITY_INFO = 3 @@ -83,13 +82,13 @@ def masked_read(self, addr, mask): # multiple byte address by 4 so it does not get # truncated because of 32 bit access of AXI4-Lite (converted to Avalon-MM) val = self.read_word(addr << 2) & mask - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: masked_read: address: " + str(hex(addr)) + ", mask: " + str(hex(mask)) + ", data: " + str(hex(val))) return val # expected byte address def masked_write(self, addr, mask, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: masked_write: address: " + str(hex(addr)) + ", mask: " + str(hex(mask) + ", data: " + str(hex(val)))) # multiple byte address by 4 so it does not get # truncated because of 32 bit access of AXI4-Lite (converted to Avalon-MM) @@ -101,13 +100,13 @@ def dump_reg_space(self, start, stop): # return True if the receiver is locked to data def get_rx_locked_to_data(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_rx_locked_to_data") return bool(self.masked_read(0x480, 0x0001)) # return True if the receiver is locked to reference clock def get_rx_locked_to_ref(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_rx_locked_to_ref") return bool(self.masked_read(0x480, 0x0002)) @@ -115,62 +114,62 @@ def get_rx_locked_to_ref(self): # presented in documentation L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 # on pages 161 - 162 def disable_background_calibration(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: disable_background_calibration") self.masked_write(0x542, 0x01, 0x00) def is_avmm_bus_busy(self): # return True if PreSICE has control of the internal configuration bus # return False if you have control of internal configuration bus - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: is_avmm_bus_busy") return bool(self.masked_read(0x481, 0x04)) def is_rx_adaption_mode_manual(self): # return True if RX adaptation is in manual mode, return False otherwise - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: is_rx_adaption_mode_manual") return bool(self.masked_read(0x161, 0x20)) def release_adaptation_from_reset(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: release_adaptation_from_reset") self.masked_write(0x148, 0x01, 0x01) def enable_cnt_to_detect_error_bits(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_cnt_to_detect_error_bits") self.masked_write(0x169, 0x40, 0x01) def enable_serial_bit_checker(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_serial_bit_checker") self.masked_write(0x168, 0x01, 0x01) def is_dfe_enabled(self): # return True if DFE is enabled, return False otherwise - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: is_dfe_enabled") return True if (self.masked_read(0x161, 0x40) == 0) else False def enable_dfe_speculation(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_dfe_speculation") self.masked_write(0x169, 0x04, 0x04) def disable_dfe_speculation(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: disable_dfe_speculation") self.masked_write(0x169, 0x04, 0x00) def enable_serial_bit_checker_control(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_serial_bit_checker_control") self.masked_write(0x158, 0x20, 0x20) # PRBS Generator registers def get_prbs_gen_prbs_tx_pma_data_sel(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs_tx_pma_data_sel") # bits[4:3] from 0x008[6:5] msb = self.masked_read(0x008, 0b1100000) >> 5 @@ -193,27 +192,27 @@ def set_prbs_gen_prbs_tx_pma_data_sel(self, val): self.masked_write(0x006, 0b00111, val & 0b00111) def get_prbs_gen_prbs9_dwidth(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs9_dwidth") return bool(self.masked_read(0x006, 0x0008)) def set_prbs_gen_prbs9_dwidth(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs9_dwidth") self.masked_write(0x006, 0x0008, 0x0008 if val else 0x0000) def get_prbs_gen_prbs_clken(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs_clken") return bool(self.masked_read(0x006, 0x0040)) def set_prbs_gen_prbs_clken(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs_clken") self.masked_write(0x006, 0x0040, 0x0040 if val else 0x0000) def get_prbs_gen_prbs_pat(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs_pat") # bit[4] from 0x008[4] msb = self.masked_read(0x008, 0x0010) @@ -247,8 +246,6 @@ def set_prbs_gen_prbs_pat(self, val): self.masked_write(0x007, 0x00F0, (val & 0x000F) << 4) def get_prbs_gen_ser_mode(self): - if (DBG_PRINT): - print("TRACE: get_prbs_gen_ser_mode") return (self.masked_read(0x110, 0x0007)) def set_prbs_gen_ser_mode(self, val): @@ -269,27 +266,27 @@ def set_prbs_gen_ser_mode(self, val): # PRBS Verifier registers def get_prbs_ver_prbs_clken(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_prbs_clken") return bool(self.masked_read(0x00A, 0x0080)) def set_prbs_ver_prbs_clken(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_prbs_clken") self.masked_write(0x00A, 0x0080, 0x0080 if val else 0x0000) def get_prbs_ver_rx_prbs_mask(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_rx_prbs_mask") return (self.masked_read(0x00B, 0x000C) >> 2) def set_prbs_ver_rx_prbs_mask(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_rx_prbs_mask") self.masked_write(0x00B, 0x000C, val << 2) def get_prbs_ver_prbs_pat(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_prbs_pat") # bit[4] from 0x00C[0] msb = self.masked_read(0x00C, 0x0001) @@ -323,17 +320,17 @@ def set_prbs_ver_prbs_pat(self, val): self.masked_write(0x00B, 0x00F0, (val & 0x000F) << 4) def get_prbs_ver_prbs9_dwidth(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_prbs9_dwidth") return bool(self.masked_read(0x00C, 0x0008)) def set_prbs_ver_prbs9_dwidth(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_prbs9_dwidth") self.masked_write(0x00C, 0x0008, 0x0008 if val else 0x0000) def get_prbs_ver_deser_factor(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_deser_factor") return (self.masked_read(0x13F, 0x000F)) @@ -355,42 +352,42 @@ def set_prbs_ver_deser_factor(self, val): # PRBS Soft Accumulators registers def get_prbs_soft_acc_prbs_counter_en(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_counter_en") return bool(self.masked_read(0x500, 0x0001)) def set_prbs_soft_acc_prbs_counter_en(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_acc_prbs_counter_en") self.masked_write(0x500, 0x0001, 0x0001 if val else 0x0000) def get_prbs_soft_acc_prbs_reset(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_reset") return bool(self.masked_read(0x500, 0x0002)) def set_prbs_soft_acc_prbs_reset(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_acc_prbs_reset") self.masked_write(0x500, 0x0002, 0x0002 if val else 0x0000) def get_prbs_soft_acc_prbs_snap(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_snap") return bool(self.masked_read(0x500, 0x0004)) def set_prbs_soft_acc_prbs_snap(self, val): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_acc_prbs_snap") self.masked_write(0x500, 0x0004, 0x0004 if val else 0x0000) def get_prbs_soft_acc_prbs_done(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_done") return bool(self.masked_read(0x500, 0x0008)) def get_prbs_soft_acc_prbs_acc_err_cnt(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_acc_err_cnt") val = 0 move_iter = 0 @@ -408,7 +405,7 @@ def get_prbs_soft_acc_prbs_acc_err_cnt(self): return val def get_prbs_soft_acc_prbs_acc_bit_cnt(self): - if (DBG_PRINT): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_acc_bit_cnt") val = 0 move_iter = 0 From c0cd92a5ceba94465d5d2925be9017f36c0367a0 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Tue, 25 Oct 2022 18:08:09 +0200 Subject: [PATCH 07/19] python/xfcp/ltile_htile_node.py: add helper function combining more write operations for each transceiver PRBS component Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 69 +++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index f834d8f3..177f911e 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -422,5 +422,74 @@ def get_prbs_soft_acc_prbs_acc_bit_cnt(self): move_iter += 1 return val + # function sets transceiver PRBS components to do BER measurement according to Intel example found on + # https://community.intel.com/t5/FPGA-Wiki/High-Speed-Transceiver-Demo-Designs-Stratix-10-GX-Series/ta-p/735749 + # and downloaded via link https://www.intel.com/content/dam/altera-www/global/en_US/uploads/1/1c/Stratix10GX_software_lib.zip + # no guide references for these operations have ben found in L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 + def set_transceiver_prbs_components(self): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): + print("TRACE: set_transceiver_prbs_components") + self.masked_write(0x164, 0x80, 0x80) + self.masked_write(0x210, 0x1F, 0x09) + self.masked_write(0x212, 0xE0, 0x00) + self.masked_write(0x213, 0xFF, 0x47) + self.masked_write(0x214, 0x01, 0x00) + self.masked_write(0x215, 0x01, 0x00) + self.masked_write(0x218, 0xC1, 0x40) + self.masked_write(0x223, 0x1F, 0x00) + self.masked_write(0x300, 0x3F, 0x00) + self.masked_write(0x312, 0xFF, 0x07) + self.masked_write(0x313, 0xFF, 0x02) + self.masked_write(0x315, 0x47, 0x00) + self.masked_write(0x318, 0x03, 0x02) + self.masked_write(0x31A, 0x1C, 0x04) + self.masked_write(0x320, 0x07, 0x02) + self.masked_write(0x321, 0x1E, 0x18) + self.masked_write(0x322, 0x73, 0x41) + + # function sets PRBS generator + def set_prbs_generator(self, prbs_pattern = "prbs31", \ + serializer_mode = 64): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): + print("TRACE: set_prbs_generator") + self.set_prbs_gen_prbs_pat(prbs_pattern) + # use PRBS pattern generator (no square wave generator) so do not make it configurable + self.set_prbs_gen_prbs_tx_pma_data_sel(PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN) + # disable PRBS 10 bit width selection + self.set_prbs_gen_prbs9_dwidth(PRBS_GENERATOR_PRBS9_DWIDTH_DISABLE) + self.set_prbs_gen_ser_mode(serializer_mode) + self.set_prbs_gen_prbs_clken(1) + + # function sets PRBS verifier + def set_prbs_verifier(self, prbs_pattern = "prbs31", \ + deserializer_factor = 64): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): + print("TRACE: set_prbs_verifier") + self.set_prbs_ver_prbs_pat(prbs_pattern) + # Following write operations has been taken from Intel example found on + # https://community.intel.com/t5/FPGA-Wiki/High-Speed-Transceiver-Demo-Designs-Stratix-10-GX-Series/ta-p/735749 + # and downloaded via link https://www.intel.com/content/dam/altera-www/global/en_US/uploads/1/1c/Stratix10GX_software_lib.zip + # no guide references for these operations have ben found in L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 + self.masked_write(0x0B, 0x0E, 0x00) + self.masked_write(0x0C, 0x0A, 0x00) + self.set_prbs_ver_deser_factor(deserializer_factor) + self.set_prbs_ver_prbs_clken(1) + + # function sets PRBS accumulator + def set_prbs_soft_accumulator(self): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): + print("TRACE: set_prbs_soft_accumulator") + self.set_prbs_soft_acc_prbs_counter_en(1) + self.set_prbs_soft_acc_prbs_reset(1) + self.set_prbs_soft_acc_prbs_reset(0) + if (self.get_prbs_soft_acc_prbs_acc_err_cnt()): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_soft_accumulator: PRBS error counter has not been reseted") + exit(1) + if (self.get_prbs_soft_acc_prbs_acc_bit_cnt()): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): + print("ERROR: set_prbs_soft_accumulator: PRBS bit counter has not been reseted") + exit(1) + node.register(LTileHTileNode, 0x9A83) From 32b20151a20bb2f743a10f1439a571ad8baf3a52 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Wed, 26 Oct 2022 11:10:12 +0200 Subject: [PATCH 08/19] python/xfcp/ltile_htile_node.py: prepare functions to return PCS PMA width instead of encoded register value Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index 177f911e..a3f98c1f 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -246,7 +246,17 @@ def set_prbs_gen_prbs_pat(self, val): self.masked_write(0x007, 0x00F0, (val & 0x000F) << 4) def get_prbs_gen_ser_mode(self): - return (self.masked_read(0x110, 0x0007)) + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): + print("TRACE: get_prbs_gen_ser_mode") + read = self.masked_read(0x110, 0x0007) + if (read == PRBS_GENERATOR_SERIALIZER_MODE_64BIT): + return 64 + elif (read == PRBS_GENERATOR_SERIALIZER_MODE_10BIT): + return 10 + else: + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_WARN): + print("WARN: get_prbs_gen_ser_mode: unknown PRBS generator serializer mode: " + str(hex(read))) + return 0 def set_prbs_gen_ser_mode(self, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): @@ -332,7 +342,15 @@ def set_prbs_ver_prbs9_dwidth(self, val): def get_prbs_ver_deser_factor(self): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_deser_factor") - return (self.masked_read(0x13F, 0x000F)) + read = self.masked_read(0x13F, 0x000F) + if (read == PRBS_VERIFIER_DESERIALIZER_FACTOR_64BIT): + return 64 + elif (read == PRBS_VERIFIER_DESERIALIZER_FACTOR_10BIT): + return 10 + else: + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_WARN): + print("WARN: get_prbs_ver_deser_factor: unknown PRBS verifier deserializer factor: " + str(hex(read))) + return 0 def set_prbs_ver_deser_factor(self, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): From fdb799d7586fbe5a2c89c431b54b291215e6c8d9 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Fri, 18 Nov 2022 12:07:06 +0100 Subject: [PATCH 09/19] python/xfcp/ltile_htile_node.py: use lane address offset in each L-Tile/H-Tile transceiver method Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 253 ++++++++++++++++---------------- 1 file changed, 127 insertions(+), 126 deletions(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index a3f98c1f..f343f96a 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -94,91 +94,91 @@ def masked_write(self, addr, mask, val): # truncated because of 32 bit access of AXI4-Lite (converted to Avalon-MM) return self.write_word(addr << 2, (self.read_word(addr << 2) & ~mask) | (val & mask)) - def dump_reg_space(self, start, stop): + def dump_reg_space(self, addr_off, start, stop): for addr in range(start, stop, 0x001): - print("Address: " + str(hex(addr)) + ": " + str(hex(self.masked_read(addr, 0xFF)))) + print("Address: " + str(hex(addr)) + ": " + str(hex(self.masked_read(addr_off, addr, 0xFF)))) # return True if the receiver is locked to data - def get_rx_locked_to_data(self): + def get_rx_locked_to_data(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_rx_locked_to_data") - return bool(self.masked_read(0x480, 0x0001)) + return bool(self.masked_read((addr_off << 11) + 0x480, 0x0001)) # return True if the receiver is locked to reference clock - def get_rx_locked_to_ref(self): + def get_rx_locked_to_ref(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_rx_locked_to_ref") - return bool(self.masked_read(0x480, 0x0002)) + return bool(self.masked_read((addr_off << 11) + 0x480, 0x0002)) # steps to follow to view Eyescan may also apply to run BER measurement # presented in documentation L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 # on pages 161 - 162 - def disable_background_calibration(self): + def disable_background_calibration(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: disable_background_calibration") - self.masked_write(0x542, 0x01, 0x00) + self.masked_write((addr_off << 11) + 0x542, 0x01, 0x00) - def is_avmm_bus_busy(self): + def is_avmm_bus_busy(self, addr_off): # return True if PreSICE has control of the internal configuration bus # return False if you have control of internal configuration bus if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: is_avmm_bus_busy") - return bool(self.masked_read(0x481, 0x04)) + return bool(self.masked_read((addr_off << 11) + 0x481, 0x04)) - def is_rx_adaption_mode_manual(self): + def is_rx_adaption_mode_manual(self, addr_off): # return True if RX adaptation is in manual mode, return False otherwise if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: is_rx_adaption_mode_manual") - return bool(self.masked_read(0x161, 0x20)) + return bool(self.masked_read((addr_off << 11) + 0x161, 0x20)) - def release_adaptation_from_reset(self): + def release_adaptation_from_reset(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: release_adaptation_from_reset") - self.masked_write(0x148, 0x01, 0x01) + self.masked_write((addr_off << 11) + 0x148, 0x01, 0x01) - def enable_cnt_to_detect_error_bits(self): + def enable_cnt_to_detect_error_bits(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_cnt_to_detect_error_bits") - self.masked_write(0x169, 0x40, 0x01) + self.masked_write((addr_off << 11) + 0x169, 0x40, 0x01) - def enable_serial_bit_checker(self): + def enable_serial_bit_checker(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_serial_bit_checker") - self.masked_write(0x168, 0x01, 0x01) + self.masked_write((addr_off << 11) + 0x168, 0x01, 0x01) - def is_dfe_enabled(self): + def is_dfe_enabled(self, addr_off): # return True if DFE is enabled, return False otherwise if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: is_dfe_enabled") - return True if (self.masked_read(0x161, 0x40) == 0) else False + return True if (self.masked_read((addr_off << 11) + 0x161, 0x40) == 0) else False - def enable_dfe_speculation(self): + def enable_dfe_speculation(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_dfe_speculation") - self.masked_write(0x169, 0x04, 0x04) + self.masked_write((addr_off << 11) + 0x169, 0x04, 0x04) - def disable_dfe_speculation(self): + def disable_dfe_speculation(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: disable_dfe_speculation") - self.masked_write(0x169, 0x04, 0x00) + self.masked_write((addr_off << 11) + 0x169, 0x04, 0x00) - def enable_serial_bit_checker_control(self): + def enable_serial_bit_checker_control(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: enable_serial_bit_checker_control") - self.masked_write(0x158, 0x20, 0x20) + self.masked_write((addr_off << 11) + 0x158, 0x20, 0x20) # PRBS Generator registers - def get_prbs_gen_prbs_tx_pma_data_sel(self): + def get_prbs_gen_prbs_tx_pma_data_sel(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs_tx_pma_data_sel") # bits[4:3] from 0x008[6:5] - msb = self.masked_read(0x008, 0b1100000) >> 5 + msb = self.masked_read((addr_off << 11) + 0x008, 0b1100000) >> 5 # bits[2:0] from 0x006[2:0] - lsb = self.masked_read(0x006, 0b00111) >> 0 + lsb = self.masked_read((addr_off << 11) + 0x006, 0b00111) >> 0 val = (msb << 3) + lsb return val - def set_prbs_gen_prbs_tx_pma_data_sel(self, val): + def set_prbs_gen_prbs_tx_pma_data_sel(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs_tx_pma_data_sel") if ((val != PRBS_GENERATOR_TX_PMA_DATA_SEL_SQUARE_WAVE) and \ @@ -187,41 +187,41 @@ def set_prbs_gen_prbs_tx_pma_data_sel(self, val): print("ERROR: set_prbs_gen_prbs_tx_pma_data_sel: unsupport TX PMA data selected: " + str(hex(val))) exit(1) # bits[4:3] to 0x008[6:5] - self.masked_write(0x008, 0b1100000, (val & 0b11000) << 2) + self.masked_write((addr_off << 11) + 0x008, 0b1100000, (val & 0b11000) << 2) # bits[2:0] to 0x006[2:0] - self.masked_write(0x006, 0b00111, val & 0b00111) + self.masked_write((addr_off << 11) + 0x006, 0b00111, val & 0b00111) - def get_prbs_gen_prbs9_dwidth(self): + def get_prbs_gen_prbs9_dwidth(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs9_dwidth") - return bool(self.masked_read(0x006, 0x0008)) + return bool(self.masked_read((addr_off << 11) + 0x006, 0x0008)) - def set_prbs_gen_prbs9_dwidth(self, val): + def set_prbs_gen_prbs9_dwidth(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs9_dwidth") - self.masked_write(0x006, 0x0008, 0x0008 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x006, 0x0008, 0x0008 if val else 0x0000) - def get_prbs_gen_prbs_clken(self): + def get_prbs_gen_prbs_clken(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs_clken") - return bool(self.masked_read(0x006, 0x0040)) + return bool(self.masked_read((addr_off << 11) + 0x006, 0x0040)) - def set_prbs_gen_prbs_clken(self, val): + def set_prbs_gen_prbs_clken(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs_clken") - self.masked_write(0x006, 0x0040, 0x0040 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x006, 0x0040, 0x0040 if val else 0x0000) - def get_prbs_gen_prbs_pat(self): + def get_prbs_gen_prbs_pat(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_prbs_pat") # bit[4] from 0x008[4] - msb = self.masked_read(0x008, 0x0010) + msb = self.masked_read((addr_off << 11) + 0x008, 0x0010) # bits[3:0] from 0x007[7:4] - lsb = self.masked_read(0x007, 0x00F0) >> 4 + lsb = self.masked_read((addr_off << 11) + 0x007, 0x00F0) >> 4 val = msb + lsb return val - def set_prbs_gen_prbs_pat(self, val): + def set_prbs_gen_prbs_pat(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_prbs_pat") # check if argument is a string and map it to register value @@ -241,14 +241,14 @@ def set_prbs_gen_prbs_pat(self, val): print("ERROR: set_prbs_gen_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) exit(1) # bit[4] to 0x008[4] - self.masked_write(0x008, 0x0010, val & 0x0010) + self.masked_write((addr_off << 11) + 0x008, 0x0010, val & 0x0010) # bits[3:0] to 0x007[7:4] - self.masked_write(0x007, 0x00F0, (val & 0x000F) << 4) + self.masked_write((addr_off << 11) + 0x007, 0x00F0, (val & 0x000F) << 4) - def get_prbs_gen_ser_mode(self): + def get_prbs_gen_ser_mode(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_gen_ser_mode") - read = self.masked_read(0x110, 0x0007) + read = self.masked_read((addr_off << 11) + 0x110, 0x0007) if (read == PRBS_GENERATOR_SERIALIZER_MODE_64BIT): return 64 elif (read == PRBS_GENERATOR_SERIALIZER_MODE_10BIT): @@ -258,7 +258,7 @@ def get_prbs_gen_ser_mode(self): print("WARN: get_prbs_gen_ser_mode: unknown PRBS generator serializer mode: " + str(hex(read))) return 0 - def set_prbs_gen_ser_mode(self, val): + def set_prbs_gen_ser_mode(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_gen_ser_mode") if type(val) is int: @@ -272,40 +272,40 @@ def set_prbs_gen_ser_mode(self, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): print("ERROR: set_prbs_gen_ser_mode: unsupported PRBS generator serializer mode: " + str(hex(val))) exit(1) - self.masked_write(0x110, 0x0007, val & 0x0007) + self.masked_write((addr_off << 11) + 0x110, 0x0007, val & 0x0007) # PRBS Verifier registers - def get_prbs_ver_prbs_clken(self): + def get_prbs_ver_prbs_clken(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_prbs_clken") - return bool(self.masked_read(0x00A, 0x0080)) + return bool(self.masked_read((addr_off << 11) + 0x00A, 0x0080)) - def set_prbs_ver_prbs_clken(self, val): + def set_prbs_ver_prbs_clken(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_prbs_clken") - self.masked_write(0x00A, 0x0080, 0x0080 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x00A, 0x0080, 0x0080 if val else 0x0000) - def get_prbs_ver_rx_prbs_mask(self): + def get_prbs_ver_rx_prbs_mask(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_rx_prbs_mask") - return (self.masked_read(0x00B, 0x000C) >> 2) + return (self.masked_read((addr_off << 11) + 0x00B, 0x000C) >> 2) - def set_prbs_ver_rx_prbs_mask(self, val): + def set_prbs_ver_rx_prbs_mask(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_rx_prbs_mask") - self.masked_write(0x00B, 0x000C, val << 2) + self.masked_write((addr_off << 11) + 0x00B, 0x000C, val << 2) - def get_prbs_ver_prbs_pat(self): + def get_prbs_ver_prbs_pat(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_prbs_pat") # bit[4] from 0x00C[0] - msb = self.masked_read(0x00C, 0x0001) + msb = self.masked_read((addr_off << 11) + 0x00C, 0x0001) # bits[3:0] from 0x00B[7:4] - lsb = self.masked_read(0x00B, 0x00F0) >> 4 + lsb = self.masked_read((addr_off << 11) + 0x00B, 0x00F0) >> 4 val = (msb << 4) + lsb return val - def set_prbs_ver_prbs_pat(self, val): + def set_prbs_ver_prbs_pat(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_prbs_pat") # check if argument is a string and map it to register value @@ -325,24 +325,24 @@ def set_prbs_ver_prbs_pat(self, val): print("ERROR: set_prbs_ver_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) exit(1) # bit[4] to 0x00C[0] - self.masked_write(0x00C, 0x0001, (val & 0x0010) >> 4) + self.masked_write((addr_off << 11) + 0x00C, 0x0001, (val & 0x0010) >> 4) # bits[3:0] to 0x00B[7:4] - self.masked_write(0x00B, 0x00F0, (val & 0x000F) << 4) + self.masked_write((addr_off << 11) + 0x00B, 0x00F0, (val & 0x000F) << 4) - def get_prbs_ver_prbs9_dwidth(self): + def get_prbs_ver_prbs9_dwidth(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_prbs9_dwidth") - return bool(self.masked_read(0x00C, 0x0008)) + return bool(self.masked_read((addr_off << 11) + 0x00C, 0x0008)) - def set_prbs_ver_prbs9_dwidth(self, val): + def set_prbs_ver_prbs9_dwidth(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_prbs9_dwidth") - self.masked_write(0x00C, 0x0008, 0x0008 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x00C, 0x0008, 0x0008 if val else 0x0000) - def get_prbs_ver_deser_factor(self): + def get_prbs_ver_deser_factor(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_ver_deser_factor") - read = self.masked_read(0x13F, 0x000F) + read = self.masked_read((addr_off << 11) + 0x13F, 0x000F) if (read == PRBS_VERIFIER_DESERIALIZER_FACTOR_64BIT): return 64 elif (read == PRBS_VERIFIER_DESERIALIZER_FACTOR_10BIT): @@ -352,7 +352,7 @@ def get_prbs_ver_deser_factor(self): print("WARN: get_prbs_ver_deser_factor: unknown PRBS verifier deserializer factor: " + str(hex(read))) return 0 - def set_prbs_ver_deser_factor(self, val): + def set_prbs_ver_deser_factor(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_ver_deser_factor") if type(val) is int: @@ -366,45 +366,45 @@ def set_prbs_ver_deser_factor(self, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): print("ERROR: set_prbs_ver_deser_factor: unsupported PRBS verifier deserializer factor: " + str(hex(val))) exit(1) - self.masked_write(0x13F, 0x000F, val & 0x000F) + self.masked_write((addr_off << 11) + 0x13F, 0x000F, val & 0x000F) # PRBS Soft Accumulators registers - def get_prbs_soft_acc_prbs_counter_en(self): + def get_prbs_soft_acc_prbs_counter_en(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_counter_en") - return bool(self.masked_read(0x500, 0x0001)) + return bool(self.masked_read((addr_off << 11) + 0x500, 0x0001)) - def set_prbs_soft_acc_prbs_counter_en(self, val): + def set_prbs_soft_acc_prbs_counter_en(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_acc_prbs_counter_en") - self.masked_write(0x500, 0x0001, 0x0001 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x500, 0x0001, 0x0001 if val else 0x0000) - def get_prbs_soft_acc_prbs_reset(self): + def get_prbs_soft_acc_prbs_reset(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_reset") - return bool(self.masked_read(0x500, 0x0002)) + return bool(self.masked_read((addr_off << 11) + 0x500, 0x0002)) - def set_prbs_soft_acc_prbs_reset(self, val): + def set_prbs_soft_acc_prbs_reset(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_acc_prbs_reset") - self.masked_write(0x500, 0x0002, 0x0002 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x500, 0x0002, 0x0002 if val else 0x0000) - def get_prbs_soft_acc_prbs_snap(self): + def get_prbs_soft_acc_prbs_snap(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_snap") - return bool(self.masked_read(0x500, 0x0004)) + return bool(self.masked_read((addr_off << 11) + 0x500, 0x0004)) - def set_prbs_soft_acc_prbs_snap(self, val): + def set_prbs_soft_acc_prbs_snap(self, addr_off, val): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_acc_prbs_snap") - self.masked_write(0x500, 0x0004, 0x0004 if val else 0x0000) + self.masked_write((addr_off << 11) + 0x500, 0x0004, 0x0004 if val else 0x0000) - def get_prbs_soft_acc_prbs_done(self): + def get_prbs_soft_acc_prbs_done(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_done") - return bool(self.masked_read(0x500, 0x0008)) + return bool(self.masked_read((addr_off << 11) + 0x500, 0x0008)) - def get_prbs_soft_acc_prbs_acc_err_cnt(self): + def get_prbs_soft_acc_prbs_acc_err_cnt(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_acc_err_cnt") val = 0 @@ -416,13 +416,13 @@ def get_prbs_soft_acc_prbs_acc_err_cnt(self): mask = 0x0003 else: mask = 0x00FF - read = self.masked_read(addr, mask) + read = self.masked_read((addr_off << 11) + addr, mask) # move each byte (8 * byte indicator) bits to the right val += read << (move_iter * 8) move_iter += 1 return val - def get_prbs_soft_acc_prbs_acc_bit_cnt(self): + def get_prbs_soft_acc_prbs_acc_bit_cnt(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: get_prbs_soft_acc_prbs_acc_bit_cnt") val = 0 @@ -434,7 +434,7 @@ def get_prbs_soft_acc_prbs_acc_bit_cnt(self): mask = 0x0003 else: mask = 0x00FF - read = self.masked_read(addr, mask) + read = self.masked_read((addr_off << 11) + addr, mask) # move each byte (8 * byte indicator) bits to the right val += read << (move_iter * 8) move_iter += 1 @@ -444,67 +444,68 @@ def get_prbs_soft_acc_prbs_acc_bit_cnt(self): # https://community.intel.com/t5/FPGA-Wiki/High-Speed-Transceiver-Demo-Designs-Stratix-10-GX-Series/ta-p/735749 # and downloaded via link https://www.intel.com/content/dam/altera-www/global/en_US/uploads/1/1c/Stratix10GX_software_lib.zip # no guide references for these operations have ben found in L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 - def set_transceiver_prbs_components(self): + def set_transceiver_prbs_components(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_transceiver_prbs_components") - self.masked_write(0x164, 0x80, 0x80) - self.masked_write(0x210, 0x1F, 0x09) - self.masked_write(0x212, 0xE0, 0x00) - self.masked_write(0x213, 0xFF, 0x47) - self.masked_write(0x214, 0x01, 0x00) - self.masked_write(0x215, 0x01, 0x00) - self.masked_write(0x218, 0xC1, 0x40) - self.masked_write(0x223, 0x1F, 0x00) - self.masked_write(0x300, 0x3F, 0x00) - self.masked_write(0x312, 0xFF, 0x07) - self.masked_write(0x313, 0xFF, 0x02) - self.masked_write(0x315, 0x47, 0x00) - self.masked_write(0x318, 0x03, 0x02) - self.masked_write(0x31A, 0x1C, 0x04) - self.masked_write(0x320, 0x07, 0x02) - self.masked_write(0x321, 0x1E, 0x18) - self.masked_write(0x322, 0x73, 0x41) + self.masked_write((addr_off << 11) + 0x164, 0x80, 0x80) + self.masked_write((addr_off << 11) + 0x210, 0x1F, 0x09) + self.masked_write((addr_off << 11) + 0x212, 0xE0, 0x00) + self.masked_write((addr_off << 11) + 0x213, 0xFF, 0x47) + self.masked_write((addr_off << 11) + 0x214, 0x01, 0x00) + self.masked_write((addr_off << 11) + 0x215, 0x01, 0x00) + self.masked_write((addr_off << 11) + 0x218, 0xC1, 0x40) + self.masked_write((addr_off << 11) + 0x223, 0x1F, 0x00) + self.masked_write((addr_off << 11) + 0x300, 0x3F, 0x00) + self.masked_write((addr_off << 11) + 0x312, 0xFF, 0x07) + self.masked_write((addr_off << 11) + 0x313, 0xFF, 0x02) + self.masked_write((addr_off << 11) + 0x315, 0x47, 0x00) + self.masked_write((addr_off << 11) + 0x318, 0x03, 0x02) + self.masked_write((addr_off << 11) + 0x31A, 0x1C, 0x04) + self.masked_write((addr_off << 11) + 0x320, 0x07, 0x02) + self.masked_write((addr_off << 11) + 0x321, 0x1E, 0x18) + self.masked_write((addr_off << 11) + 0x322, 0x73, 0x41) # function sets PRBS generator - def set_prbs_generator(self, prbs_pattern = "prbs31", \ + def set_prbs_generator(self, addr_off, prbs_pattern = "prbs31", \ serializer_mode = 64): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_generator") - self.set_prbs_gen_prbs_pat(prbs_pattern) + self.set_prbs_gen_prbs_pat(addr_off, prbs_pattern) # use PRBS pattern generator (no square wave generator) so do not make it configurable - self.set_prbs_gen_prbs_tx_pma_data_sel(PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN) + self.set_prbs_gen_prbs_tx_pma_data_sel(addr_off, PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN) # disable PRBS 10 bit width selection - self.set_prbs_gen_prbs9_dwidth(PRBS_GENERATOR_PRBS9_DWIDTH_DISABLE) - self.set_prbs_gen_ser_mode(serializer_mode) - self.set_prbs_gen_prbs_clken(1) + self.set_prbs_gen_prbs9_dwidth(addr_off, PRBS_GENERATOR_PRBS9_DWIDTH_DISABLE) + self.set_prbs_gen_ser_mode(addr_off, serializer_mode) + self.set_prbs_gen_prbs_clken(addr_off, 1) # function sets PRBS verifier - def set_prbs_verifier(self, prbs_pattern = "prbs31", \ + def set_prbs_verifier(self, addr_off, prbs_pattern = "prbs31", \ deserializer_factor = 64): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_verifier") - self.set_prbs_ver_prbs_pat(prbs_pattern) + self.set_prbs_ver_prbs_pat(addr_off, prbs_pattern) # Following write operations has been taken from Intel example found on # https://community.intel.com/t5/FPGA-Wiki/High-Speed-Transceiver-Demo-Designs-Stratix-10-GX-Series/ta-p/735749 # and downloaded via link https://www.intel.com/content/dam/altera-www/global/en_US/uploads/1/1c/Stratix10GX_software_lib.zip # no guide references for these operations have ben found in L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 - self.masked_write(0x0B, 0x0E, 0x00) - self.masked_write(0x0C, 0x0A, 0x00) - self.set_prbs_ver_deser_factor(deserializer_factor) - self.set_prbs_ver_prbs_clken(1) + self.masked_write((addr_off << 11) + 0x0B, 0x0E, 0x00) + self.masked_write((addr_off << 11) + 0x0C, 0x0A, 0x00) + self.set_prbs_ver_deser_factor(addr_off, deserializer_factor) + self.set_prbs_ver_prbs_clken(addr_off, 1) # function sets PRBS accumulator - def set_prbs_soft_accumulator(self): + def set_prbs_soft_accumulator(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_prbs_soft_accumulator") - self.set_prbs_soft_acc_prbs_counter_en(1) - self.set_prbs_soft_acc_prbs_reset(1) - self.set_prbs_soft_acc_prbs_reset(0) - if (self.get_prbs_soft_acc_prbs_acc_err_cnt()): + self.set_prbs_soft_acc_prbs_counter_en(addr_off, 1) + self.set_prbs_soft_acc_prbs_reset(addr_off, 1) + self.set_prbs_soft_acc_prbs_reset(addr_off, 0) + self.set_prbs_soft_acc_prbs_snap(addr_off, 0) + if (self.get_prbs_soft_acc_prbs_acc_err_cnt(addr_off)): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): print("ERROR: set_prbs_soft_accumulator: PRBS error counter has not been reseted") exit(1) - if (self.get_prbs_soft_acc_prbs_acc_bit_cnt()): + if (self.get_prbs_soft_acc_prbs_acc_bit_cnt(addr_off)): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): print("ERROR: set_prbs_soft_accumulator: PRBS bit counter has not been reseted") exit(1) From c0f592f084246c64aa192d5819dc80f604580bb2 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Tue, 22 Nov 2022 16:58:50 +0100 Subject: [PATCH 10/19] python/xfcp/ltile_htile_node.py: squash set_prbs_generator and set_prbs_verifier methods, use exact configuration sequence from Intel SW Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 34 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index f343f96a..305bd825 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -465,33 +465,23 @@ def set_transceiver_prbs_components(self, addr_off): self.masked_write((addr_off << 11) + 0x321, 0x1E, 0x18) self.masked_write((addr_off << 11) + 0x322, 0x73, 0x41) - # function sets PRBS generator - def set_prbs_generator(self, addr_off, prbs_pattern = "prbs31", \ - serializer_mode = 64): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): - print("TRACE: set_prbs_generator") - self.set_prbs_gen_prbs_pat(addr_off, prbs_pattern) - # use PRBS pattern generator (no square wave generator) so do not make it configurable - self.set_prbs_gen_prbs_tx_pma_data_sel(addr_off, PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN) - # disable PRBS 10 bit width selection - self.set_prbs_gen_prbs9_dwidth(addr_off, PRBS_GENERATOR_PRBS9_DWIDTH_DISABLE) - self.set_prbs_gen_ser_mode(addr_off, serializer_mode) - self.set_prbs_gen_prbs_clken(addr_off, 1) - - # function sets PRBS verifier - def set_prbs_verifier(self, addr_off, prbs_pattern = "prbs31", \ + # function sets PRBS generator and PRBS verifier + def set_prbs_gen_and_ver(self, addr_off, \ + prbs_pattern = "prbs31", \ + serializer_mode = 64, \ deserializer_factor = 64): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): - print("TRACE: set_prbs_verifier") + print("TRACE: set_prbs_gen_and_ver") + self.set_prbs_gen_prbs_pat(addr_off, prbs_pattern) self.set_prbs_ver_prbs_pat(addr_off, prbs_pattern) - # Following write operations has been taken from Intel example found on - # https://community.intel.com/t5/FPGA-Wiki/High-Speed-Transceiver-Demo-Designs-Stratix-10-GX-Series/ta-p/735749 - # and downloaded via link https://www.intel.com/content/dam/altera-www/global/en_US/uploads/1/1c/Stratix10GX_software_lib.zip - # no guide references for these operations have ben found in L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 + self.set_prbs_gen_ser_mode(addr_off, serializer_mode) + self.masked_write((addr_off << 11) + 0x06, 0xCF, 0x44) self.masked_write((addr_off << 11) + 0x0B, 0x0E, 0x00) self.masked_write((addr_off << 11) + 0x0C, 0x0A, 0x00) - self.set_prbs_ver_deser_factor(addr_off, deserializer_factor) - self.set_prbs_ver_prbs_clken(addr_off, 1) + self.set_prbs_ver_deser_factor(addr_off, serializer_mode) + self.masked_write((addr_off << 11) + 0x0A, 0x80, 0x80) + self.masked_write((addr_off << 11) + 0x500, 0x07, 0x01) + # function sets PRBS accumulator def set_prbs_soft_accumulator(self, addr_off): From 18d17c98ab9b5eb8f5f01abe4dd15f8e2056ddb2 Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Tue, 22 Nov 2022 17:02:02 +0100 Subject: [PATCH 11/19] python/xfcp/ltile_htile_node.py: add method for transceiver bounded channels configuration reversed engineered from register space dump dump taken after BERT test run in system-console SW Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index 305bd825..41061c8b 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -482,6 +482,16 @@ def set_prbs_gen_and_ver(self, addr_off, \ self.masked_write((addr_off << 11) + 0x0A, 0x80, 0x80) self.masked_write((addr_off << 11) + 0x500, 0x07, 0x01) + def set_transceiver_bounded_channels_configuration(self, addr_off): + if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): + print("TRACE: set_transceiver_bounded_channels_configuration") + self.masked_write((addr_off << 11) + 0x0B, 0x02, 0x02) + self.masked_write((addr_off << 11) + 0x0C, 0x02, 0x02) + self.masked_write((addr_off << 11) + 0x10A, 0x01, 0x00) + self.masked_write((addr_off << 11) + 0x10B, 0x01, 0x01) + self.masked_write((addr_off << 11) + 0x111, 0x19, 0x18) + self.masked_write((addr_off << 11) + 0x123, 0xC0, 0x80) + self.masked_write((addr_off << 11) + 0x12A, 0x90, 0x90) # function sets PRBS accumulator def set_prbs_soft_accumulator(self, addr_off): From 9fd8e934767e5c319f8ac20fc43f5573ac5b72cd Mon Sep 17 00:00:00 2001 From: Karol Budniak Date: Tue, 22 Nov 2022 17:28:05 +0100 Subject: [PATCH 12/19] python/xfcp/ltile_htile_node.py: add configurable call for reverse engineered method with bounded channels configuration Signed-off-by: Karol Budniak --- python/xfcp/ltile_htile_node.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index 41061c8b..8eb23bed 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -468,6 +468,7 @@ def set_transceiver_prbs_components(self, addr_off): # function sets PRBS generator and PRBS verifier def set_prbs_gen_and_ver(self, addr_off, \ prbs_pattern = "prbs31", \ + use_bounded_channels_config = False, \ serializer_mode = 64, \ deserializer_factor = 64): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): @@ -481,7 +482,14 @@ def set_prbs_gen_and_ver(self, addr_off, \ self.set_prbs_ver_deser_factor(addr_off, serializer_mode) self.masked_write((addr_off << 11) + 0x0A, 0x80, 0x80) self.masked_write((addr_off << 11) + 0x500, 0x07, 0x01) - + if (use_bounded_channels_config): + self.set_transceiver_bounded_channels_configuration(addr_off) + + # function performs bounded channels transceiver configuration + # reverse engineered from transceiver register space dump + # taken after successful BERT test for PCIe transceiver + # neither Intel SW example perform these steps, nor they have not been described in + # L- and H-Tile Transceiver PHY User Guide 683621 | 2022.07.20 def set_transceiver_bounded_channels_configuration(self, addr_off): if (PRINT_VERBOSITY >= PRINT_VERBOSITY_TRACE): print("TRACE: set_transceiver_bounded_channels_configuration") From 05114b82116b078c0e4ced7f816c2bab60a8778d Mon Sep 17 00:00:00 2001 From: Tobias Binkowski Date: Mon, 11 Dec 2023 14:34:56 +0100 Subject: [PATCH 13/19] python: node.py, add get_by_name to retrieve a named xfcp instance --- python/xfcp/node.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/xfcp/node.py b/python/xfcp/node.py index c8d9863a..01f59ef7 100644 --- a/python/xfcp/node.py +++ b/python/xfcp/node.py @@ -113,6 +113,16 @@ def get_by_path(self, path): return n + def get_by_name(self, name, recursive=True): + for n in self.children: + if n.name == name: + return n + if recursive and len(n.children): + ret = n.get_by_name(name, recursive) + if ret: + return ret + return None + def find_by_type(self, t, prefix=16): l = [] From f703cb406d5f75fe4849146b295d9ff8dfa39ffa Mon Sep 17 00:00:00 2001 From: Tobias Binkowski Date: Wed, 13 Dec 2023 10:25:26 +0100 Subject: [PATCH 14/19] python: ltile_htile_node, replace all exit calls with raising exceptions --- python/xfcp/ltile_htile_node.py | 44 +++++++++------------------------ 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index 8eb23bed..398222a9 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -183,9 +183,7 @@ def set_prbs_gen_prbs_tx_pma_data_sel(self, addr_off, val): print("TRACE: set_prbs_gen_prbs_tx_pma_data_sel") if ((val != PRBS_GENERATOR_TX_PMA_DATA_SEL_SQUARE_WAVE) and \ (val != PRBS_GENERATOR_TX_PMA_DATA_SEL_PRBS_PATTERN)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_gen_prbs_tx_pma_data_sel: unsupport TX PMA data selected: " + str(hex(val))) - exit(1) + raise Exception("set_prbs_gen_prbs_tx_pma_data_sel: unsupport TX PMA data selected: " + str(hex(val))) # bits[4:3] to 0x008[6:5] self.masked_write((addr_off << 11) + 0x008, 0b1100000, (val & 0b11000) << 2) # bits[2:0] to 0x006[2:0] @@ -228,18 +226,14 @@ def set_prbs_gen_prbs_pat(self, addr_off, val): if type(val) is str: val = prbs_mode_mapping[val] else: - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_gen_prbs_pat: argument given is not a string") - exit(1) + raise Exception("set_prbs_gen_prbs_pat: argument given is not a string") if ((val != PRBS_MODE_OFF) and \ (val != PRBS_MODE_PRBS7) and \ (val != PRBS_MODE_PRBS9) and \ (val != PRBS_MODE_PRBS15) and \ (val != PRBS_MODE_PRBS23) and \ (val != PRBS_MODE_PRBS31)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_gen_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) - exit(1) + raise Exception("set_prbs_gen_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) # bit[4] to 0x008[4] self.masked_write((addr_off << 11) + 0x008, 0x0010, val & 0x0010) # bits[3:0] to 0x007[7:4] @@ -264,14 +258,10 @@ def set_prbs_gen_ser_mode(self, addr_off, val): if type(val) is int: val = prbs_generator_serializer_mode_mapping[val] else: - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_gen_ser_mode: argument given is not an integer") - exit(1) + raise Exception("set_prbs_gen_ser_mode: argument given is not an integer") if ((val != PRBS_GENERATOR_SERIALIZER_MODE_64BIT) and (val != PRBS_GENERATOR_SERIALIZER_MODE_10BIT)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_gen_ser_mode: unsupported PRBS generator serializer mode: " + str(hex(val))) - exit(1) + raise Exception("set_prbs_gen_ser_mode: unsupported PRBS generator serializer mode: " + str(hex(val))) self.masked_write((addr_off << 11) + 0x110, 0x0007, val & 0x0007) # PRBS Verifier registers @@ -312,18 +302,14 @@ def set_prbs_ver_prbs_pat(self, addr_off, val): if type(val) is str: val = prbs_mode_mapping[val] else: - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_ver_prbs_pat: argument given is not a string") - exit(1) + raise Exception("set_prbs_ver_prbs_pat: argument given is not a string") if ((val != PRBS_MODE_OFF) and \ (val != PRBS_MODE_PRBS7) and \ (val != PRBS_MODE_PRBS9) and \ (val != PRBS_MODE_PRBS15) and \ (val != PRBS_MODE_PRBS23) and \ (val != PRBS_MODE_PRBS31)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_ver_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) - exit(1) + raise Exception("set_prbs_ver_prbs_pat: unsupported PRBS pattern selected: " + str(hex(val))) # bit[4] to 0x00C[0] self.masked_write((addr_off << 11) + 0x00C, 0x0001, (val & 0x0010) >> 4) # bits[3:0] to 0x00B[7:4] @@ -358,14 +344,10 @@ def set_prbs_ver_deser_factor(self, addr_off, val): if type(val) is int: val = prbs_verifier_deserializer_factor_mapping[val] else: - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_ver_deser_factor: argument given is not an integer") - exit(1) + raise Exception("set_prbs_ver_deser_factor: argument given is not an integer") if ((val != PRBS_VERIFIER_DESERIALIZER_FACTOR_64BIT) and (val != PRBS_VERIFIER_DESERIALIZER_FACTOR_10BIT)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_ver_deser_factor: unsupported PRBS verifier deserializer factor: " + str(hex(val))) - exit(1) + raise Exception("set_prbs_ver_deser_factor: unsupported PRBS verifier deserializer factor: " + str(hex(val))) self.masked_write((addr_off << 11) + 0x13F, 0x000F, val & 0x000F) # PRBS Soft Accumulators registers @@ -510,13 +492,9 @@ def set_prbs_soft_accumulator(self, addr_off): self.set_prbs_soft_acc_prbs_reset(addr_off, 0) self.set_prbs_soft_acc_prbs_snap(addr_off, 0) if (self.get_prbs_soft_acc_prbs_acc_err_cnt(addr_off)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_soft_accumulator: PRBS error counter has not been reseted") - exit(1) + raise Exception("set_prbs_soft_accumulator: PRBS error counter has not been reseted") if (self.get_prbs_soft_acc_prbs_acc_bit_cnt(addr_off)): - if (PRINT_VERBOSITY >= PRINT_VERBOSITY_ERROR): - print("ERROR: set_prbs_soft_accumulator: PRBS bit counter has not been reseted") - exit(1) + raise Exception("set_prbs_soft_accumulator: PRBS bit counter has not been reseted") node.register(LTileHTileNode, 0x9A83) From 053184931f07cf9d966565697ee37d03ed4acc1b Mon Sep 17 00:00:00 2001 From: Ulrich Langenbach Date: Tue, 26 Sep 2023 21:16:48 +0200 Subject: [PATCH 15/19] python: build paython package of xfcp library --- .gitignore | 4 +++- python/Makefile | 26 ++++++++++++++++++++++++++ python/pyproject.toml | 39 +++++++++++++++++++++++++++++++++++++++ python/requirements.txt | 1 + 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 python/Makefile create mode 100644 python/pyproject.toml create mode 100644 python/requirements.txt diff --git a/.gitignore b/.gitignore index 964df4d4..b8689225 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ *.pyc *.vvp *.kate-swp - +python/xfcp.egg-info +python/build/ +python/venv/ diff --git a/python/Makefile b/python/Makefile new file mode 100644 index 00000000..25aea057 --- /dev/null +++ b/python/Makefile @@ -0,0 +1,26 @@ +MKFILE_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +VENVDIR = venv +VENVACTIVATE = $(VENVDIR)/bin/activate +XFCP_DIR = $(MKFILE_DIR)/ +PYTHON_VERSION=$(shell python3 -c "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));sys.stdout.write(t)") + +.PHONY: xfcp + +venv: $(VENVACTIVATE) + +xfcp: venv + . $(VENVACTIVATE) && \ + pip install $(XFCP_DIR) + +$(VENVACTIVATE): requirements.txt + test -d $(VENVDIR) || python3 -m venv $(VENVDIR) --copies + . $(VENVACTIVATE) && \ + pip3 install wheel && \ + pip3 install -r requirements.txt && \ + touch $(VENVACTIVATE) + +clean: + rm -rf __pycache__ + +mrproper: clean + rm -rf $(VENVDIR) diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 00000000..4e329922 --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,39 @@ +##Copyright (c) 2023 Jakob Arndt Missing Link Electronics, Inc. +## +##Permission is hereby granted, free of charge, to any person obtaining a copy +##of this software and associated documentation files (the "Software"), to deal +##in the Software without restriction, including without limitation the rights +##to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +##copies of the Software, and to permit persons to whom the Software is +##furnished to do so, subject to the following conditions: +## +##The above copyright notice and this permission notice shall be included in +##all copies or substantial portions of the Software. +## +##THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +##IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +##FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +##AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +##LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +##OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +##THE SOFTWARE. + +[build-system] +requires = ["setuptools", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[project] +name = "xfcp" +authors = [{name="Alex Forencich", email="jforenci@eng.ucsd.edu"}] +description="This python package enables the use of xfcp as a library for your python implementation." +version = "1.0" +requires-python = ">=3.6" +dependencies = [ + "pyserial" +] + +[tool.setuptools] +packages = ['xfcp'] + +[tool.setuptools.package-dir] +"xfcp" = "xfcp" diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 00000000..f6c1a1f5 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1 @@ +pyserial From c7f7e4d02f59905999781c15f15a0f79d9025b37 Mon Sep 17 00:00:00 2001 From: Ulrich Langenbach Date: Wed, 27 Sep 2023 20:25:10 +0200 Subject: [PATCH 16/19] xfcp/python: add alternative packaging method support via setup.py --- .gitignore | 1 + python/setup.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 python/setup.py diff --git a/.gitignore b/.gitignore index b8689225..5154d16d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ python/xfcp.egg-info python/build/ python/venv/ +python/.eggs/ diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 00000000..8ae94a41 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,38 @@ +##Copyright (c) 2023 Jakob Arndt Missing Link Electronics, Inc. +## +##Permission is hereby granted, free of charge, to any person obtaining a copy +##of this software and associated documentation files (the "Software"), to deal +##in the Software without restriction, including without limitation the rights +##to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +##copies of the Software, and to permit persons to whom the Software is +##furnished to do so, subject to the following conditions: +## +##The above copyright notice and this permission notice shall be included in +##all copies or substantial portions of the Software. +## +##THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +##IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +##FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +##AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +##LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +##OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +##THE SOFTWARE. + +from setuptools import setup + +setup( + name="xfcp", + version="1.0.0", + description="This python package enables you to control the NPAP Test FPGA", + author="Alex Forencich", + author_email="jforenci@eng.ucsd.edu", + packages=[ + 'xfcp'], + package_dir={ + "xfcp": "xfcp" + }, + setup_requires=['setuptools_scm'], + install_requires=[ + 'pyserial', + ] +) From f481504446d8922787f8f1c0c88f81c7b7711eaa Mon Sep 17 00:00:00 2001 From: Ulrich Langenbach Date: Fri, 17 Nov 2023 10:56:03 +0100 Subject: [PATCH 17/19] python/packaging: add version check to support old and new style install procedure --- python/Makefile | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/python/Makefile b/python/Makefile index 25aea057..9d86a2fe 100644 --- a/python/Makefile +++ b/python/Makefile @@ -2,7 +2,14 @@ MKFILE_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) VENVDIR = venv VENVACTIVATE = $(VENVDIR)/bin/activate XFCP_DIR = $(MKFILE_DIR)/ -PYTHON_VERSION=$(shell python3 -c "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));sys.stdout.write(t)") +PYTHON_VERSION=$(shell python3 -c "import sys; v = list(sys.version_info[:2]); print(f'{int(v[0])}.{int(v[1])}')") +ifeq ($(PYTHON_VERSION), 3.6) +$(info Python Version supported) +else ifeq ($(PYTHON_VERSION), 3.10) +$(info Python Version supported) +else +$(error Python Version not supported, the supported versions are 3.6 and 3.10) +endif .PHONY: xfcp @@ -10,7 +17,11 @@ venv: $(VENVACTIVATE) xfcp: venv . $(VENVACTIVATE) && \ - pip install $(XFCP_DIR) + if [ $(PYTHON_VERSION) = "3.6" ]; then \ + python setup.py install; \ + else \ + pip install $(XFCP_DIR); \ + fi \ $(VENVACTIVATE): requirements.txt test -d $(VENVDIR) || python3 -m venv $(VENVDIR) --copies From 5bdd4b654d3948204ae96386711178fc9f984f0a Mon Sep 17 00:00:00 2001 From: Jakob Arndt Date: Mon, 3 Oct 2022 22:30:16 +0200 Subject: [PATCH 18/19] Changes to use Labgrid with XFCP This commit modifies the interface class, in a way that it is possible to utilize the serial instance created by labgrid. To use it a SerialDriver class has to passed to the __init__ function as a forth parameter. Signed-off-by: Jakob Arndt --- python/xfcp/interface.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/python/xfcp/interface.py b/python/xfcp/interface.py index 3db1ebb3..d590ef85 100644 --- a/python/xfcp/interface.py +++ b/python/xfcp/interface.py @@ -108,12 +108,20 @@ def get_root(self): class SerialInterface(Interface): - def __init__(self, port='/dev/ttyUSB0', baud=115200, timeout=10): + def __init__(self, port='/dev/ttyUSB0', baud=115200, timeout=10, driver=None): + """ + driver is expected to be a SerialDriver class from the labgrid module + """ super().__init__() self.port = port self.baud = baud - self.serial_port = serial.Serial(port, baud, timeout=timeout) + + # if labgrid driver is given, use labgrid driver + if driver is None: + self.serial_port = serial.Serial(port, baud, timeout=timeout) + else: + self.serial_port = driver.serial @property def timeout(self): From 5066e4d7ccf57272bcb950c0634ba67584b3275f Mon Sep 17 00:00:00 2001 From: Tobias Binkowski Date: Mon, 18 Dec 2023 10:37:45 +0100 Subject: [PATCH 19/19] python/xfcp: ltile_htile_node, fix dump_reg_space function --- python/xfcp/ltile_htile_node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/xfcp/ltile_htile_node.py b/python/xfcp/ltile_htile_node.py index 398222a9..9a69a6dc 100644 --- a/python/xfcp/ltile_htile_node.py +++ b/python/xfcp/ltile_htile_node.py @@ -96,7 +96,7 @@ def masked_write(self, addr, mask, val): def dump_reg_space(self, addr_off, start, stop): for addr in range(start, stop, 0x001): - print("Address: " + str(hex(addr)) + ": " + str(hex(self.masked_read(addr_off, addr, 0xFF)))) + print("Address: " + str(hex(addr)) + ": " + str(hex(self.masked_read(addr, 0xFF)))) # return True if the receiver is locked to data def get_rx_locked_to_data(self, addr_off):