From cacbcb6fcfea866319b6571dd541aae709cd106d Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jan 2024 16:16:29 -0600 Subject: [PATCH 001/163] Created the basic synthesizable wally tracer for fpga. --- src/wally/rvvisynth.sv | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/wally/rvvisynth.sv diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv new file mode 100644 index 000000000..457cf05e2 --- /dev/null +++ b/src/wally/rvvisynth.sv @@ -0,0 +1,72 @@ +/////////////////////////////////////////// +// rvvisynth.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: 23 January 2024 +// Modified: 23 January 2024 +// +// Purpose: Synthesizable rvvi bridge from Wally to generic compressed format. +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module rvvisynth import cvw::*; #(parameter cvw_t P, + parameter integer MAX_CSR)( + input logic clk, reset, + output logic valid, + output logic [163+P.XLEN-1:0] Requied, + output logic [12+2*P.XLEN-1:0] Registers, + output logic [12+MAX_CSR*(P.XLEN+12)-1:0] CSRs + ); + + logic [P.XLEN-1:0] PCM, PCW; + logic StallW, FlushW; + logic InstrValidM, InstrValidW; + logic [31:0] InstrRawD, InstrRawE, InstrRawM, InstrRawW; + logic [63:0] Mcycle, Minstret; + logic TrapM, TrapW; + logic [1:0] PrivilegeModeW; + + // get signals from the core. + assign StallW = testbench.dut.core.StallW; + assign FlushW = testbench.dut.core.FlushW; + assign InstrValidM = testbench.dut.core.ieu.InstrValidM; + assign InstrRawD = testbench.dut.core.ifu.InstrRawD; + assign PCM = testbench.dut.core.ifu.PCM; + assign Mcycle = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = testbench.dut.core.TrapM; + assign PrivilegeModeW = testbench.dut.core.priv.priv.privmode.PrivilegeModeW; + + // start out easy and just populate Required + // PC, inst, mcycle, minstret, trap, mode + + flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW); + flopenrc #(P.XLEN) PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW); + flopenrc #(32) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE); + flopenrc #(32) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM); + flopenrc #(32) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW); + flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW); + + assign valid = InstrValidW & ~StallW; + assign Required = {PrivilegeModeW, TrapW, Minstret, Mcycle, InstrRawW, PCW}; + +endmodule + From 0babb011c2f51b1849876b4458e00dc489a05f24 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jan 2024 16:27:50 -0600 Subject: [PATCH 002/163] Synthesizable rvvi tracer output G/FPRs. --- src/wally/rvvisynth.sv | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv index 457cf05e2..2d894696d 100644 --- a/src/wally/rvvisynth.sv +++ b/src/wally/rvvisynth.sv @@ -36,13 +36,20 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, output logic [12+MAX_CSR*(P.XLEN+12)-1:0] CSRs ); - logic [P.XLEN-1:0] PCM, PCW; + // pipeline controlls logic StallW, FlushW; + // required + logic [P.XLEN-1:0] PCM, PCW; logic InstrValidM, InstrValidW; logic [31:0] InstrRawD, InstrRawE, InstrRawM, InstrRawW; logic [63:0] Mcycle, Minstret; logic TrapM, TrapW; logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] XLENZeros; // get signals from the core. assign StallW = testbench.dut.core.StallW; @@ -50,23 +57,37 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign InstrValidM = testbench.dut.core.ieu.InstrValidM; assign InstrRawD = testbench.dut.core.ifu.InstrRawD; assign PCM = testbench.dut.core.ifu.PCM; - assign Mcycle = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign Mcycle = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; assign TrapM = testbench.dut.core.TrapM; assign PrivilegeModeW = testbench.dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = testbench.dut.core.ieu.dp.regf.a3; + assign GPRWen = testbench.dut.core.ieu.dp.regf.we3; + assign GPRValue = testbench.dut.core.ieu.dp.regf.wd3; + assign FPRAddr = testbench.dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = testbench.dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = testbench.dut.core.fpu.fpu.fregfile.wd4; + + + // + assign XLENZeros = '0; // start out easy and just populate Required // PC, inst, mcycle, minstret, trap, mode - flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW); + flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW); flopenrc #(P.XLEN) PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW); - flopenrc #(32) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE); - flopenrc #(32) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM); - flopenrc #(32) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW); - flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW); + flopenrc #(32) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE); + flopenrc #(32) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM); + flopenrc #(32) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW); + flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW); assign valid = InstrValidW & ~StallW; assign Required = {PrivilegeModeW, TrapW, Minstret, Mcycle, InstrRawW, PCW}; - + assign Registers = {FPRWen, GPRWen} == 2'b11 ? {FPRValue, FPRAddr, GPRValue, GPRAddr, FPRWen, GPRWen} : + {FPRWen, GPRWen} == 2'b01 ? {XLENZeros, 5'b0, GPRValue, GPRAddr, FPRWen, GPRWen} : + {FPRWen, GPRWen} == 2'b10 ? {FPRValue, FPRAddr, XLENZeros, 5'b0, FPRWen, GPRWen} : + {XLENZeros, 5'b0, XLENZeros, 5'b0, FPRWen, GPRWen}; + endmodule From fd032a7e106cfe2022b5afb6d1d8e7f467256603 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 24 Jan 2024 15:06:13 -0600 Subject: [PATCH 003/163] Draft implementation of synth rvvi. --- src/wally/csrindextoaddr.sv | 77 ++++++++++++++++++++++++++++++++++++ src/wally/priorityaomux.sv | 47 ++++++++++++++++++++++ src/wally/regchangedetect.sv | 41 +++++++++++++++++++ src/wally/rvvisynth.sv | 73 ++++++++++++++++++++++++++++++++-- 4 files changed, 235 insertions(+), 3 deletions(-) create mode 100644 src/wally/csrindextoaddr.sv create mode 100644 src/wally/priorityaomux.sv create mode 100644 src/wally/regchangedetect.sv diff --git a/src/wally/csrindextoaddr.sv b/src/wally/csrindextoaddr.sv new file mode 100644 index 000000000..e06508bdf --- /dev/null +++ b/src/wally/csrindextoaddr.sv @@ -0,0 +1,77 @@ +/////////////////////////////////////////// +// csrindextoaddr.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: 24 January 2024 +// Modified: 24 January 2024 +// +// Purpose: Converts the rvvi CSR index into the CSR address +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module csrindextoaddr #(parameter NUM_CSRS = 36) ( + input logic [ROWS-1:0] CSRWen, + output logic [11:0] CSRAddr); + + always_comb begin + case(CSRWen) begin + 36'h0_0000_0000: CSRAddr = 13'h000; + 36'h0_0000_0001: CSRAddr = 13'h300; + 36'h0_0000_0002: CSRAddr = 13'h310; + 36'h0_0000_0004: CSRAddr = 13'h305; + 36'h0_0000_0008: CSRAddr = 13'h341; + 36'h0_0000_0010: CSRAddr = 13'h306; + 36'h0_0000_0020: CSRAddr = 13'h320; + 36'h0_0000_0040: CSRAddr = 13'h302; + 36'h0_0000_0080: CSRAddr = 13'h303; + 36'h0_0000_0100: CSRAddr = 13'h344; + 36'h0_0000_0200: CSRAddr = 13'h304; + 36'h0_0000_0400: CSRAddr = 13'h301; + 36'h0_0000_0800: CSRAddr = 13'h30A; + 36'h0_0000_1000: CSRAddr = 13'hF14; + 36'h0_0000_2000: CSRAddr = 13'h340; + 36'h0_0000_4000: CSRAddr = 13'h342; + 36'h0_0000_8000: CSRAddr = 13'h343; + 36'h0_0001_0000: CSRAddr = 13'hF11; + 36'h0_0002_0000: CSRAddr = 13'hF12; + 36'h0_0004_0000: CSRAddr = 13'hF13; + 36'h0_0008_0000: CSRAddr = 13'hF15; + 36'h0_0010_0000: CSRAddr = 13'h34A; + 36'h0_0020_0000: CSRAddr = 13'h100; + 36'h0_0040_0000: CSRAddr = 13'h104; + 36'h0_0080_0000: CSRAddr = 13'h105; + 36'h0_0100_0000: CSRAddr = 13'h141; + 36'h0_0200_0000: CSRAddr = 13'h106; + 36'h0_0400_0000: CSRAddr = 13'h10A; + 36'h0_0800_0000: CSRAddr = 13'h180; + 36'h0_1000_0000: CSRAddr = 13'h140; + 36'h0_2000_0000: CSRAddr = 13'h143; + 36'h0_4000_0000: CSRAddr = 13'h142; + 36'h0_8000_0000: CSRAddr = 13'h144; + 36'h1_0000_0000: CSRAddr = 13'h14D; + 36'h2_0000_0000: CSRAddr = 13'h001; + 36'h4_0000_0000: CSRAddr = 13'h002; + 36'h8_0000_0000: CSRAddr = 13'h003; + default : CSRAddr = 13'h000; + end + end +endmodule + diff --git a/src/wally/priorityaomux.sv b/src/wally/priorityaomux.sv new file mode 100644 index 000000000..c99b0e1ed --- /dev/null +++ b/src/wally/priorityaomux.sv @@ -0,0 +1,47 @@ +/////////////////////////////////////////// +// priorityaomux.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: 24 January 2024 +// Modified: 24 January 2024 +// +// Purpose: priority AND-OR MUX. +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module priorityaomux #(parameter ROWS = 8, COLS = 64) ( + input logic [ROWS-1:0] Sel, + input var logic [COLS-1:0] A [ROWS-1:0], + output logic [COLS-1:0] Y, + output logic [ROWS-1:0] SelPriority); + + logic [ROWS-1:0] SelPriority; + logic [COLS-1:0] AMasked [ROWS-1:0]; + genvar index; + + priorityonehot #(ROWS) priorityonehot(Sel, SelPriority); + for(index = 0; index < ROWS; index = index + 1) begin + assign AMasked[index] = SelPriority[index] ? A[index] : '0; + end + or_rows #(ROWS, COLS) or_rows(AMasked, Y); + +endmodule + diff --git a/src/wally/regchangedetect.sv b/src/wally/regchangedetect.sv new file mode 100644 index 000000000..8becf867d --- /dev/null +++ b/src/wally/regchangedetect.sv @@ -0,0 +1,41 @@ +/////////////////////////////////////////// +// regchangedetect.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: 24 January 2024 +// Modified: 24 January 2024 +// +// Purpose: +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module regchangedetect #(parameter XLEN = 64) ( + input clk, reset, + input logic [XLEN-1:0] Value, + output logic Change); + + logic [XLEN-1:0] ValueD; + + flopr #(XLEN) register(clk, reset, Value, ValueD); + assign Change = |(Value ^ ValueD); + +endmodule + diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv index 2d894696d..019000915 100644 --- a/src/wally/rvvisynth.sv +++ b/src/wally/rvvisynth.sv @@ -28,14 +28,16 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module rvvisynth import cvw::*; #(parameter cvw_t P, - parameter integer MAX_CSR)( + parameter integer MAX_CSRS)( input logic clk, reset, output logic valid, output logic [163+P.XLEN-1:0] Requied, output logic [12+2*P.XLEN-1:0] Registers, - output logic [12+MAX_CSR*(P.XLEN+12)-1:0] CSRs + output logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs ); + localparam TOTAL_CSRS = 36; + // pipeline controlls logic StallW, FlushW; // required @@ -50,7 +52,12 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [4:0] GPRAddr, FPRAddr; logic [P.XLEN-1:0] GPRValue, FPRValue; logic [P.XLEN-1:0] XLENZeros; - + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + logic [TOTAL_CSRS-1:0] CSRArrayWen; + logic [MAX_CSRS-1:0] CSRValue [P.XLEN-1:0]; + logic [MAX_CSRS-1:0] CSRWen [TOTAL_CSRS-1:0]; + logic [MAX_CSRS-1:0] CSRAddr [11:0]; + // get signals from the core. assign StallW = testbench.dut.core.StallW; assign FlushW = testbench.dut.core.FlushW; @@ -68,6 +75,44 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign FPRWen = testbench.dut.core.fpu.fpu.fregfile.we4; assign FPRValue = testbench.dut.core.fpu.fpu.fregfile.wd4; + assign CSRArray[0] = testbench.dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = testbench.dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = testbench.dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = testbench.dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = testbench.dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = testbench.dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = testbench.dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = testbench.dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = testbench.dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = testbench.dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = testbench.dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = testbench.dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = testbench.dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = testbench.dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW, testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 // assign XLENZeros = '0; @@ -89,5 +134,27 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, {FPRWen, GPRWen} == 2'b10 ? {FPRValue, FPRAddr, XLENZeros, 5'b0, FPRWen, GPRWen} : {XLENZeros, 5'b0, XLENZeros, 5'b0, FPRWen, GPRWen}; + // the CSRs are complex + // 1. we need to get the CSR values + // 2. we check if the CSR value changes by registering the value then XORing with the old value. + // 3. Then use priorityaomux to collect CSR values and addresses for compating into the compressed rvvi format + + // step 2 + genvar index; + for (index = 0; index < TOTAL_CSRS; index = index + 1) begin + regchangedetect #(P.XLEN) changedetect(clk, reset, CSRArray[index], CSRArrayWen[index]); + end + + // step 3a + for(index = 0; index < MAX_CSRS; index = index + 1) begin + logic [NUM_CSRS-index-1:0] CSRWenShort; + priorityaomux #(NUM_CSRS-index, P.XLEN) priorityaomux(CSRArrayWen[MAX_CSRS-1:index], CSRArray[MAX_CSRS-1:index], CSRValue[index], CSRWenShort); + assign CSRWen[index] = {{{index}{1'b0}}, CSRWenShort}; + // step 3b + csrindextoaddr #(NUM_CSRS) csrindextoaddr(CSRWen, CSRAddr); + assign CSRs[(index+1) * P.XLEN - 1 + 12 + 12: index * P.XLEN + 12] = {CSRValue[index], CSRAddr[index]}; + end + + endmodule From 29db2cd931e95e4d429941d03404858c66f5ce56 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 8 Mar 2024 12:38:27 -0600 Subject: [PATCH 004/163] Basic hardware tracer works! Next step is to package the buses into packets to ethernet transmission. --- sim/wave.do | 186 ++++++++++++++++++++------------- src/wally/csrindextoaddr.sv | 8 +- src/wally/priorityaomux.sv | 1 - src/wally/rvvisynth.sv | 21 ++-- src/wally/wallypipelinedsoc.sv | 8 ++ 5 files changed, 134 insertions(+), 90 deletions(-) diff --git a/sim/wave.do b/sim/wave.do index 8717f667d..41cb4ba42 100644 --- a/sim/wave.do +++ b/sim/wave.do @@ -1,48 +1,68 @@ onerror {resume} quietly virtual signal -install /testbench/dut/core/ifu/bpred/bpred { /testbench/dut/core/ifu/bpred/bpred/PostSpillInstrRawF[11:7]} rd +quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[11], /testbench/dut/rvvisynth/CSRs[10], /testbench/dut/rvvisynth/CSRs[9], /testbench/dut/rvvisynth/CSRs[8], /testbench/dut/rvvisynth/CSRs[7], /testbench/dut/rvvisynth/CSRs[6], /testbench/dut/rvvisynth/CSRs[5], /testbench/dut/rvvisynth/CSRs[4], /testbench/dut/rvvisynth/CSRs[3], /testbench/dut/rvvisynth/CSRs[2], /testbench/dut/rvvisynth/CSRs[1], /testbench/dut/rvvisynth/CSRs[0] }} NumCSRs +quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[23], /testbench/dut/rvvisynth/CSRs[22], /testbench/dut/rvvisynth/CSRs[21], /testbench/dut/rvvisynth/CSRs[20], /testbench/dut/rvvisynth/CSRs[19], /testbench/dut/rvvisynth/CSRs[18], /testbench/dut/rvvisynth/CSRs[17], /testbench/dut/rvvisynth/CSRs[16], /testbench/dut/rvvisynth/CSRs[15], /testbench/dut/rvvisynth/CSRs[14], /testbench/dut/rvvisynth/CSRs[13], /testbench/dut/rvvisynth/CSRs[12] }} CSRAdr0 +quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[87], /testbench/dut/rvvisynth/CSRs[86], /testbench/dut/rvvisynth/CSRs[85], /testbench/dut/rvvisynth/CSRs[84], /testbench/dut/rvvisynth/CSRs[83], /testbench/dut/rvvisynth/CSRs[82], /testbench/dut/rvvisynth/CSRs[81], /testbench/dut/rvvisynth/CSRs[80], /testbench/dut/rvvisynth/CSRs[79], /testbench/dut/rvvisynth/CSRs[78], /testbench/dut/rvvisynth/CSRs[77], /testbench/dut/rvvisynth/CSRs[76], /testbench/dut/rvvisynth/CSRs[75], /testbench/dut/rvvisynth/CSRs[74], /testbench/dut/rvvisynth/CSRs[73], /testbench/dut/rvvisynth/CSRs[72], /testbench/dut/rvvisynth/CSRs[71], /testbench/dut/rvvisynth/CSRs[70], /testbench/dut/rvvisynth/CSRs[69], /testbench/dut/rvvisynth/CSRs[68], /testbench/dut/rvvisynth/CSRs[67], /testbench/dut/rvvisynth/CSRs[66], /testbench/dut/rvvisynth/CSRs[65], /testbench/dut/rvvisynth/CSRs[64], /testbench/dut/rvvisynth/CSRs[63], /testbench/dut/rvvisynth/CSRs[62], /testbench/dut/rvvisynth/CSRs[61], /testbench/dut/rvvisynth/CSRs[60], /testbench/dut/rvvisynth/CSRs[59], /testbench/dut/rvvisynth/CSRs[58], /testbench/dut/rvvisynth/CSRs[57], /testbench/dut/rvvisynth/CSRs[56], /testbench/dut/rvvisynth/CSRs[55], /testbench/dut/rvvisynth/CSRs[54], /testbench/dut/rvvisynth/CSRs[53], /testbench/dut/rvvisynth/CSRs[52], /testbench/dut/rvvisynth/CSRs[51], /testbench/dut/rvvisynth/CSRs[50], /testbench/dut/rvvisynth/CSRs[49], /testbench/dut/rvvisynth/CSRs[48], /testbench/dut/rvvisynth/CSRs[47], /testbench/dut/rvvisynth/CSRs[46], /testbench/dut/rvvisynth/CSRs[45], /testbench/dut/rvvisynth/CSRs[44], /testbench/dut/rvvisynth/CSRs[43], /testbench/dut/rvvisynth/CSRs[42], /testbench/dut/rvvisynth/CSRs[41], /testbench/dut/rvvisynth/CSRs[40], /testbench/dut/rvvisynth/CSRs[39], /testbench/dut/rvvisynth/CSRs[38], /testbench/dut/rvvisynth/CSRs[37], /testbench/dut/rvvisynth/CSRs[36], /testbench/dut/rvvisynth/CSRs[35], /testbench/dut/rvvisynth/CSRs[34], /testbench/dut/rvvisynth/CSRs[33], /testbench/dut/rvvisynth/CSRs[32], /testbench/dut/rvvisynth/CSRs[31], /testbench/dut/rvvisynth/CSRs[30], /testbench/dut/rvvisynth/CSRs[29], /testbench/dut/rvvisynth/CSRs[28], /testbench/dut/rvvisynth/CSRs[27], /testbench/dut/rvvisynth/CSRs[26], /testbench/dut/rvvisynth/CSRs[25], /testbench/dut/rvvisynth/CSRs[24] }} CSRData0 +quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[163], /testbench/dut/rvvisynth/CSRs[162], /testbench/dut/rvvisynth/CSRs[161], /testbench/dut/rvvisynth/CSRs[160], /testbench/dut/rvvisynth/CSRs[159], /testbench/dut/rvvisynth/CSRs[158], /testbench/dut/rvvisynth/CSRs[157], /testbench/dut/rvvisynth/CSRs[156], /testbench/dut/rvvisynth/CSRs[155], /testbench/dut/rvvisynth/CSRs[154], /testbench/dut/rvvisynth/CSRs[153], /testbench/dut/rvvisynth/CSRs[152], /testbench/dut/rvvisynth/CSRs[151], /testbench/dut/rvvisynth/CSRs[150], /testbench/dut/rvvisynth/CSRs[149], /testbench/dut/rvvisynth/CSRs[148], /testbench/dut/rvvisynth/CSRs[147], /testbench/dut/rvvisynth/CSRs[146], /testbench/dut/rvvisynth/CSRs[145], /testbench/dut/rvvisynth/CSRs[144], /testbench/dut/rvvisynth/CSRs[143], /testbench/dut/rvvisynth/CSRs[142], /testbench/dut/rvvisynth/CSRs[141], /testbench/dut/rvvisynth/CSRs[140], /testbench/dut/rvvisynth/CSRs[139], /testbench/dut/rvvisynth/CSRs[138], /testbench/dut/rvvisynth/CSRs[137], /testbench/dut/rvvisynth/CSRs[136], /testbench/dut/rvvisynth/CSRs[135], /testbench/dut/rvvisynth/CSRs[134], /testbench/dut/rvvisynth/CSRs[133], /testbench/dut/rvvisynth/CSRs[132], /testbench/dut/rvvisynth/CSRs[131], /testbench/dut/rvvisynth/CSRs[130], /testbench/dut/rvvisynth/CSRs[129], /testbench/dut/rvvisynth/CSRs[128], /testbench/dut/rvvisynth/CSRs[127], /testbench/dut/rvvisynth/CSRs[126], /testbench/dut/rvvisynth/CSRs[125], /testbench/dut/rvvisynth/CSRs[124], /testbench/dut/rvvisynth/CSRs[123], /testbench/dut/rvvisynth/CSRs[122], /testbench/dut/rvvisynth/CSRs[121], /testbench/dut/rvvisynth/CSRs[120], /testbench/dut/rvvisynth/CSRs[119], /testbench/dut/rvvisynth/CSRs[118], /testbench/dut/rvvisynth/CSRs[117], /testbench/dut/rvvisynth/CSRs[116], /testbench/dut/rvvisynth/CSRs[115], /testbench/dut/rvvisynth/CSRs[114], /testbench/dut/rvvisynth/CSRs[113], /testbench/dut/rvvisynth/CSRs[112], /testbench/dut/rvvisynth/CSRs[111], /testbench/dut/rvvisynth/CSRs[110], /testbench/dut/rvvisynth/CSRs[109], /testbench/dut/rvvisynth/CSRs[108], /testbench/dut/rvvisynth/CSRs[107], /testbench/dut/rvvisynth/CSRs[106], /testbench/dut/rvvisynth/CSRs[105], /testbench/dut/rvvisynth/CSRs[104], /testbench/dut/rvvisynth/CSRs[103], /testbench/dut/rvvisynth/CSRs[102], /testbench/dut/rvvisynth/CSRs[101], /testbench/dut/rvvisynth/CSRs[100] }} CSRData1 +quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[175], /testbench/dut/rvvisynth/CSRs[174], /testbench/dut/rvvisynth/CSRs[173], /testbench/dut/rvvisynth/CSRs[172], /testbench/dut/rvvisynth/CSRs[171], /testbench/dut/rvvisynth/CSRs[170], /testbench/dut/rvvisynth/CSRs[169], /testbench/dut/rvvisynth/CSRs[168], /testbench/dut/rvvisynth/CSRs[167], /testbench/dut/rvvisynth/CSRs[166], /testbench/dut/rvvisynth/CSRs[165], /testbench/dut/rvvisynth/CSRs[164] }} CSRAdr2 +quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[239], /testbench/dut/rvvisynth/CSRs[238], /testbench/dut/rvvisynth/CSRs[237], /testbench/dut/rvvisynth/CSRs[236], /testbench/dut/rvvisynth/CSRs[235], /testbench/dut/rvvisynth/CSRs[234], /testbench/dut/rvvisynth/CSRs[233], /testbench/dut/rvvisynth/CSRs[232], /testbench/dut/rvvisynth/CSRs[231], /testbench/dut/rvvisynth/CSRs[230], /testbench/dut/rvvisynth/CSRs[229], /testbench/dut/rvvisynth/CSRs[228], /testbench/dut/rvvisynth/CSRs[227], /testbench/dut/rvvisynth/CSRs[226], /testbench/dut/rvvisynth/CSRs[225], /testbench/dut/rvvisynth/CSRs[224], /testbench/dut/rvvisynth/CSRs[223], /testbench/dut/rvvisynth/CSRs[222], /testbench/dut/rvvisynth/CSRs[221], /testbench/dut/rvvisynth/CSRs[220], /testbench/dut/rvvisynth/CSRs[219], /testbench/dut/rvvisynth/CSRs[218], /testbench/dut/rvvisynth/CSRs[217], /testbench/dut/rvvisynth/CSRs[216], /testbench/dut/rvvisynth/CSRs[215], /testbench/dut/rvvisynth/CSRs[214], /testbench/dut/rvvisynth/CSRs[213], /testbench/dut/rvvisynth/CSRs[212], /testbench/dut/rvvisynth/CSRs[211], /testbench/dut/rvvisynth/CSRs[210], /testbench/dut/rvvisynth/CSRs[209], /testbench/dut/rvvisynth/CSRs[208], /testbench/dut/rvvisynth/CSRs[207], /testbench/dut/rvvisynth/CSRs[206], /testbench/dut/rvvisynth/CSRs[205], /testbench/dut/rvvisynth/CSRs[204], /testbench/dut/rvvisynth/CSRs[203], /testbench/dut/rvvisynth/CSRs[202], /testbench/dut/rvvisynth/CSRs[201], /testbench/dut/rvvisynth/CSRs[200], /testbench/dut/rvvisynth/CSRs[199], /testbench/dut/rvvisynth/CSRs[198], /testbench/dut/rvvisynth/CSRs[197], /testbench/dut/rvvisynth/CSRs[196], /testbench/dut/rvvisynth/CSRs[195], /testbench/dut/rvvisynth/CSRs[194], /testbench/dut/rvvisynth/CSRs[193], /testbench/dut/rvvisynth/CSRs[192], /testbench/dut/rvvisynth/CSRs[191], /testbench/dut/rvvisynth/CSRs[190], /testbench/dut/rvvisynth/CSRs[189], /testbench/dut/rvvisynth/CSRs[188], /testbench/dut/rvvisynth/CSRs[187], /testbench/dut/rvvisynth/CSRs[186], /testbench/dut/rvvisynth/CSRs[185], /testbench/dut/rvvisynth/CSRs[184], /testbench/dut/rvvisynth/CSRs[183], /testbench/dut/rvvisynth/CSRs[182], /testbench/dut/rvvisynth/CSRs[181], /testbench/dut/rvvisynth/CSRs[180], /testbench/dut/rvvisynth/CSRs[179], /testbench/dut/rvvisynth/CSRs[178], /testbench/dut/rvvisynth/CSRs[177], /testbench/dut/rvvisynth/CSRs[176] }} CSRData2 +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[63], /testbench/dut/Required[62], /testbench/dut/Required[61], /testbench/dut/Required[60], /testbench/dut/Required[59], /testbench/dut/Required[58], /testbench/dut/Required[57], /testbench/dut/Required[56], /testbench/dut/Required[55], /testbench/dut/Required[54], /testbench/dut/Required[53], /testbench/dut/Required[52], /testbench/dut/Required[51], /testbench/dut/Required[50], /testbench/dut/Required[49], /testbench/dut/Required[48], /testbench/dut/Required[47], /testbench/dut/Required[46], /testbench/dut/Required[45], /testbench/dut/Required[44], /testbench/dut/Required[43], /testbench/dut/Required[42], /testbench/dut/Required[41], /testbench/dut/Required[40], /testbench/dut/Required[39], /testbench/dut/Required[38], /testbench/dut/Required[37], /testbench/dut/Required[36], /testbench/dut/Required[35], /testbench/dut/Required[34], /testbench/dut/Required[33], /testbench/dut/Required[32], /testbench/dut/Required[31], /testbench/dut/Required[30], /testbench/dut/Required[29], /testbench/dut/Required[28], /testbench/dut/Required[27], /testbench/dut/Required[26], /testbench/dut/Required[25], /testbench/dut/Required[24], /testbench/dut/Required[23], /testbench/dut/Required[22], /testbench/dut/Required[21], /testbench/dut/Required[20], /testbench/dut/Required[19], /testbench/dut/Required[18], /testbench/dut/Required[17], /testbench/dut/Required[16], /testbench/dut/Required[15], /testbench/dut/Required[14], /testbench/dut/Required[13], /testbench/dut/Required[12], /testbench/dut/Required[11], /testbench/dut/Required[10], /testbench/dut/Required[9], /testbench/dut/Required[8], /testbench/dut/Required[7], /testbench/dut/Required[6], /testbench/dut/Required[5], /testbench/dut/Required[4], /testbench/dut/Required[3], /testbench/dut/Required[2], /testbench/dut/Required[1], /testbench/dut/Required[0] }} PCW +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[95], /testbench/dut/Required[94], /testbench/dut/Required[93], /testbench/dut/Required[92], /testbench/dut/Required[91], /testbench/dut/Required[90], /testbench/dut/Required[89], /testbench/dut/Required[88], /testbench/dut/Required[87], /testbench/dut/Required[86], /testbench/dut/Required[85], /testbench/dut/Required[84], /testbench/dut/Required[83], /testbench/dut/Required[82], /testbench/dut/Required[81], /testbench/dut/Required[80], /testbench/dut/Required[79], /testbench/dut/Required[78], /testbench/dut/Required[77], /testbench/dut/Required[76], /testbench/dut/Required[75], /testbench/dut/Required[74], /testbench/dut/Required[73], /testbench/dut/Required[72], /testbench/dut/Required[71], /testbench/dut/Required[70], /testbench/dut/Required[69], /testbench/dut/Required[68], /testbench/dut/Required[67], /testbench/dut/Required[66], /testbench/dut/Required[65], /testbench/dut/Required[64] }} InstrW +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[159], /testbench/dut/Required[158], /testbench/dut/Required[157], /testbench/dut/Required[156], /testbench/dut/Required[155], /testbench/dut/Required[154], /testbench/dut/Required[153], /testbench/dut/Required[152], /testbench/dut/Required[151], /testbench/dut/Required[150], /testbench/dut/Required[149], /testbench/dut/Required[148], /testbench/dut/Required[147], /testbench/dut/Required[146], /testbench/dut/Required[145], /testbench/dut/Required[144], /testbench/dut/Required[143], /testbench/dut/Required[142], /testbench/dut/Required[141], /testbench/dut/Required[140], /testbench/dut/Required[139], /testbench/dut/Required[138], /testbench/dut/Required[137], /testbench/dut/Required[136], /testbench/dut/Required[135], /testbench/dut/Required[134], /testbench/dut/Required[133], /testbench/dut/Required[132], /testbench/dut/Required[131], /testbench/dut/Required[130], /testbench/dut/Required[129], /testbench/dut/Required[128], /testbench/dut/Required[127], /testbench/dut/Required[126], /testbench/dut/Required[125], /testbench/dut/Required[124], /testbench/dut/Required[123], /testbench/dut/Required[122], /testbench/dut/Required[121], /testbench/dut/Required[120], /testbench/dut/Required[119], /testbench/dut/Required[118], /testbench/dut/Required[117], /testbench/dut/Required[116], /testbench/dut/Required[115], /testbench/dut/Required[114], /testbench/dut/Required[113], /testbench/dut/Required[112], /testbench/dut/Required[111], /testbench/dut/Required[110], /testbench/dut/Required[109], /testbench/dut/Required[108], /testbench/dut/Required[107], /testbench/dut/Required[106], /testbench/dut/Required[105], /testbench/dut/Required[104], /testbench/dut/Required[103], /testbench/dut/Required[102], /testbench/dut/Required[101], /testbench/dut/Required[100], /testbench/dut/Required[99], /testbench/dut/Required[98], /testbench/dut/Required[97], /testbench/dut/Required[96] }} Mcycle +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[223], /testbench/dut/Required[222], /testbench/dut/Required[221], /testbench/dut/Required[220], /testbench/dut/Required[219], /testbench/dut/Required[218], /testbench/dut/Required[217], /testbench/dut/Required[216], /testbench/dut/Required[215], /testbench/dut/Required[214], /testbench/dut/Required[213], /testbench/dut/Required[212], /testbench/dut/Required[211], /testbench/dut/Required[210], /testbench/dut/Required[209], /testbench/dut/Required[208], /testbench/dut/Required[207], /testbench/dut/Required[206], /testbench/dut/Required[205], /testbench/dut/Required[204], /testbench/dut/Required[203], /testbench/dut/Required[202], /testbench/dut/Required[201], /testbench/dut/Required[200], /testbench/dut/Required[199], /testbench/dut/Required[198], /testbench/dut/Required[197], /testbench/dut/Required[196], /testbench/dut/Required[195], /testbench/dut/Required[194], /testbench/dut/Required[193], /testbench/dut/Required[192], /testbench/dut/Required[191], /testbench/dut/Required[190], /testbench/dut/Required[189], /testbench/dut/Required[188], /testbench/dut/Required[187], /testbench/dut/Required[186], /testbench/dut/Required[185], /testbench/dut/Required[184], /testbench/dut/Required[183], /testbench/dut/Required[182], /testbench/dut/Required[181], /testbench/dut/Required[180], /testbench/dut/Required[179], /testbench/dut/Required[178], /testbench/dut/Required[177], /testbench/dut/Required[176], /testbench/dut/Required[175], /testbench/dut/Required[174], /testbench/dut/Required[173], /testbench/dut/Required[172], /testbench/dut/Required[171], /testbench/dut/Required[170], /testbench/dut/Required[169], /testbench/dut/Required[168], /testbench/dut/Required[167], /testbench/dut/Required[166], /testbench/dut/Required[165], /testbench/dut/Required[164], /testbench/dut/Required[163], /testbench/dut/Required[162], /testbench/dut/Required[161], /testbench/dut/Required[160] }} Minstret +quietly virtual signal -install /testbench/dut {/testbench/dut/Required[224] } TrapW +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[226], /testbench/dut/Required[225] }} PrivilegeModeW +quietly virtual signal -install /testbench/dut {/testbench/dut/Registers[0] } GPRWen +quietly virtual signal -install /testbench/dut {/testbench/dut/Registers[1] } FPRWen +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[6], /testbench/dut/Registers[5], /testbench/dut/Registers[4], /testbench/dut/Registers[3], /testbench/dut/Registers[2] }} GPRAdr +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[71], /testbench/dut/Registers[70], /testbench/dut/Registers[69], /testbench/dut/Registers[68], /testbench/dut/Registers[67], /testbench/dut/Registers[66], /testbench/dut/Registers[65], /testbench/dut/Registers[64], /testbench/dut/Registers[63], /testbench/dut/Registers[62], /testbench/dut/Registers[61], /testbench/dut/Registers[60], /testbench/dut/Registers[59], /testbench/dut/Registers[58], /testbench/dut/Registers[57], /testbench/dut/Registers[56], /testbench/dut/Registers[55], /testbench/dut/Registers[54], /testbench/dut/Registers[53], /testbench/dut/Registers[52], /testbench/dut/Registers[51], /testbench/dut/Registers[50], /testbench/dut/Registers[49], /testbench/dut/Registers[48], /testbench/dut/Registers[47], /testbench/dut/Registers[46], /testbench/dut/Registers[45], /testbench/dut/Registers[44], /testbench/dut/Registers[43], /testbench/dut/Registers[42], /testbench/dut/Registers[41], /testbench/dut/Registers[40], /testbench/dut/Registers[39], /testbench/dut/Registers[38], /testbench/dut/Registers[37], /testbench/dut/Registers[36], /testbench/dut/Registers[35], /testbench/dut/Registers[34], /testbench/dut/Registers[33], /testbench/dut/Registers[32], /testbench/dut/Registers[31], /testbench/dut/Registers[30], /testbench/dut/Registers[29], /testbench/dut/Registers[28], /testbench/dut/Registers[27], /testbench/dut/Registers[26], /testbench/dut/Registers[25], /testbench/dut/Registers[24], /testbench/dut/Registers[23], /testbench/dut/Registers[22], /testbench/dut/Registers[21], /testbench/dut/Registers[20], /testbench/dut/Registers[19], /testbench/dut/Registers[18], /testbench/dut/Registers[17], /testbench/dut/Registers[16], /testbench/dut/Registers[15], /testbench/dut/Registers[14], /testbench/dut/Registers[13], /testbench/dut/Registers[12], /testbench/dut/Registers[11], /testbench/dut/Registers[10], /testbench/dut/Registers[9], /testbench/dut/Registers[8], /testbench/dut/Registers[7] }} GPRValue +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[76], /testbench/dut/Registers[75], /testbench/dut/Registers[74], /testbench/dut/Registers[73], /testbench/dut/Registers[72], /testbench/dut/Registers[71] }} GPRAdr001 +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[139], /testbench/dut/Registers[138], /testbench/dut/Registers[137], /testbench/dut/Registers[136], /testbench/dut/Registers[135], /testbench/dut/Registers[134], /testbench/dut/Registers[133], /testbench/dut/Registers[132], /testbench/dut/Registers[131], /testbench/dut/Registers[130], /testbench/dut/Registers[129], /testbench/dut/Registers[128], /testbench/dut/Registers[127], /testbench/dut/Registers[126], /testbench/dut/Registers[125], /testbench/dut/Registers[124], /testbench/dut/Registers[123], /testbench/dut/Registers[122], /testbench/dut/Registers[121], /testbench/dut/Registers[120], /testbench/dut/Registers[119], /testbench/dut/Registers[118], /testbench/dut/Registers[117], /testbench/dut/Registers[116], /testbench/dut/Registers[115], /testbench/dut/Registers[114], /testbench/dut/Registers[113], /testbench/dut/Registers[112], /testbench/dut/Registers[111], /testbench/dut/Registers[110], /testbench/dut/Registers[109], /testbench/dut/Registers[108], /testbench/dut/Registers[107], /testbench/dut/Registers[106], /testbench/dut/Registers[105], /testbench/dut/Registers[104], /testbench/dut/Registers[103], /testbench/dut/Registers[102], /testbench/dut/Registers[101], /testbench/dut/Registers[100], /testbench/dut/Registers[99], /testbench/dut/Registers[98], /testbench/dut/Registers[97], /testbench/dut/Registers[96], /testbench/dut/Registers[95], /testbench/dut/Registers[94], /testbench/dut/Registers[93], /testbench/dut/Registers[92], /testbench/dut/Registers[91], /testbench/dut/Registers[90], /testbench/dut/Registers[89], /testbench/dut/Registers[88], /testbench/dut/Registers[87], /testbench/dut/Registers[86], /testbench/dut/Registers[85], /testbench/dut/Registers[84], /testbench/dut/Registers[83], /testbench/dut/Registers[82], /testbench/dut/Registers[81], /testbench/dut/Registers[80], /testbench/dut/Registers[79], /testbench/dut/Registers[78], /testbench/dut/Registers[77], /testbench/dut/Registers[76] }} FPRValue +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[70], /testbench/dut/Registers[69], /testbench/dut/Registers[68], /testbench/dut/Registers[67], /testbench/dut/Registers[66], /testbench/dut/Registers[65], /testbench/dut/Registers[64], /testbench/dut/Registers[63], /testbench/dut/Registers[62], /testbench/dut/Registers[61], /testbench/dut/Registers[60], /testbench/dut/Registers[59], /testbench/dut/Registers[58], /testbench/dut/Registers[57], /testbench/dut/Registers[56], /testbench/dut/Registers[55], /testbench/dut/Registers[54], /testbench/dut/Registers[53], /testbench/dut/Registers[52], /testbench/dut/Registers[51], /testbench/dut/Registers[50], /testbench/dut/Registers[49], /testbench/dut/Registers[48], /testbench/dut/Registers[47], /testbench/dut/Registers[46], /testbench/dut/Registers[45], /testbench/dut/Registers[44], /testbench/dut/Registers[43], /testbench/dut/Registers[42], /testbench/dut/Registers[41], /testbench/dut/Registers[40], /testbench/dut/Registers[39], /testbench/dut/Registers[38], /testbench/dut/Registers[37], /testbench/dut/Registers[36], /testbench/dut/Registers[35], /testbench/dut/Registers[34], /testbench/dut/Registers[33], /testbench/dut/Registers[32], /testbench/dut/Registers[31], /testbench/dut/Registers[30], /testbench/dut/Registers[29], /testbench/dut/Registers[28], /testbench/dut/Registers[27], /testbench/dut/Registers[26], /testbench/dut/Registers[25], /testbench/dut/Registers[24], /testbench/dut/Registers[23], /testbench/dut/Registers[22], /testbench/dut/Registers[21], /testbench/dut/Registers[20], /testbench/dut/Registers[19], /testbench/dut/Registers[18], /testbench/dut/Registers[17], /testbench/dut/Registers[16], /testbench/dut/Registers[15], /testbench/dut/Registers[14], /testbench/dut/Registers[13], /testbench/dut/Registers[12], /testbench/dut/Registers[11], /testbench/dut/Registers[10], /testbench/dut/Registers[9], /testbench/dut/Registers[8], /testbench/dut/Registers[7] }} GPRValue001 +quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[75], /testbench/dut/Registers[74], /testbench/dut/Registers[73], /testbench/dut/Registers[72], /testbench/dut/Registers[71] }} FPRAdr quietly WaveActivateNextPane {} 0 add wave -noupdate /testbench/clk add wave -noupdate /testbench/reset add wave -noupdate /testbench/memfilename add wave -noupdate /testbench/dut/core/SATP_REGW add wave -noupdate /testbench/dut/core/InstrValidM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/hzu/RetM -add wave -noupdate -expand -group HDU -expand -group hazards -color Pink /testbench/dut/core/hzu/TrapM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/ieu/c/LoadStallD -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/ifu/IFUStallF -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/hzu/BPWrongE -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/hzu/LSUStallM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/ieu/c/MDUStallD -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/hzu/DivBusyE -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/core/hzu/FDivBusyE -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrMisalignedFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/IllegalInstrFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/BreakpointFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadMisalignedFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoMisalignedFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/EcallFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrPageFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadPageFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoPageFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InterruptM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/HPTWInstrAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/core/priv/priv/pmd/WFITimeoutM -add wave -noupdate -expand -group HDU -group Flush -color Yellow /testbench/dut/core/FlushD -add wave -noupdate -expand -group HDU -group Flush -color Yellow /testbench/dut/core/FlushE -add wave -noupdate -expand -group HDU -group Flush -color Yellow /testbench/dut/core/FlushM -add wave -noupdate -expand -group HDU -group Flush -color Yellow /testbench/dut/core/FlushW -add wave -noupdate -expand -group HDU -group Stall -color Orange /testbench/dut/core/StallF -add wave -noupdate -expand -group HDU -group Stall -color Orange /testbench/dut/core/StallD -add wave -noupdate -expand -group HDU -group Stall -color Orange /testbench/dut/core/StallE -add wave -noupdate -expand -group HDU -group Stall -color Orange /testbench/dut/core/StallM -add wave -noupdate -expand -group HDU -group Stall -color Orange /testbench/dut/core/StallW -add wave -noupdate -expand -group HDU -group interrupts /testbench/dut/core/priv/priv/trap/PendingIntsM -add wave -noupdate -expand -group HDU -group interrupts /testbench/dut/core/priv/priv/trap/InstrValidM -add wave -noupdate -expand -group HDU -group interrupts /testbench/dut/core/priv/priv/trap/ValidIntsM -add wave -noupdate -expand -group HDU -group interrupts /testbench/dut/core/hzu/WFIInterruptedM +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/RetM +add wave -noupdate -group HDU -expand -group hazards -color Pink /testbench/dut/core/hzu/TrapM +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/ieu/c/LoadStallD +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/ifu/IFUStallF +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/BPWrongE +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/LSUStallM +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/ieu/c/MDUStallD +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/DivBusyE +add wave -noupdate -group HDU -expand -group hazards /testbench/dut/core/hzu/FDivBusyE +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrMisalignedFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrAccessFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/IllegalInstrFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/BreakpointFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadMisalignedFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoMisalignedFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadAccessFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoAccessFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/EcallFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrPageFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadPageFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoPageFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InterruptM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/HPTWInstrAccessFaultM +add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/pmd/WFITimeoutM +add wave -noupdate -group HDU -group Flush -color Yellow /testbench/dut/core/FlushD +add wave -noupdate -group HDU -group Flush -color Yellow /testbench/dut/core/FlushE +add wave -noupdate -group HDU -group Flush -color Yellow /testbench/dut/core/FlushM +add wave -noupdate -group HDU -group Flush -color Yellow /testbench/dut/core/FlushW +add wave -noupdate -group HDU -group Stall -color Orange /testbench/dut/core/StallF +add wave -noupdate -group HDU -group Stall -color Orange /testbench/dut/core/StallD +add wave -noupdate -group HDU -group Stall -color Orange /testbench/dut/core/StallE +add wave -noupdate -group HDU -group Stall -color Orange /testbench/dut/core/StallM +add wave -noupdate -group HDU -group Stall -color Orange /testbench/dut/core/StallW +add wave -noupdate -group HDU -group interrupts /testbench/dut/core/priv/priv/trap/PendingIntsM +add wave -noupdate -group HDU -group interrupts /testbench/dut/core/priv/priv/trap/InstrValidM +add wave -noupdate -group HDU -group interrupts /testbench/dut/core/priv/priv/trap/ValidIntsM +add wave -noupdate -group HDU -group interrupts /testbench/dut/core/hzu/WFIInterruptedM add wave -noupdate -group {instruction pipeline} /testbench/InstrFName add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/PostSpillInstrRawF add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/InstrD @@ -239,7 +259,6 @@ add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/z add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/ziccslm_align/align/SelSpillM add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/ByteMaskSpillM add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/LSUWriteDataM -add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/LSUWriteDataSpillM add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/bus/dcache/dcache/CacheWriteData add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/bus/dcache/dcache/ByteMask add wave -noupdate -expand -group lsu -group alignment /testbench/dut/core/lsu/bus/dcache/dcache/WriteSelLogic/BlankByteMask @@ -252,20 +271,18 @@ add wave -noupdate -expand -group lsu /testbench/dut/core/lsu/bus/dcache/dcache/ add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu/bus/dcache/dcache/CacheRW add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu/bus/dcache/dcache/CMOpM add wave -noupdate -expand -group lsu -expand -group dcache -color Gold /testbench/dut/core/lsu/bus/dcache/dcache/cachefsm/CurrState -add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/SetValid -add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/ClearValid -add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/SetDirty -add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/ClearDirty -add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/SelWay -add wave -noupdate -expand -group lsu -expand -group dcache -group {requesting address} /testbench/dut/core/lsu/IEUAdrE -add wave -noupdate -expand -group lsu -expand -group dcache -group {requesting address} /testbench/dut/core/lsu/bus/dcache/dcache/PAdr +add wave -noupdate -expand -group lsu -expand -group dcache -expand -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/SetValid +add wave -noupdate -expand -group lsu -expand -group dcache -expand -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/ClearValid +add wave -noupdate -expand -group lsu -expand -group dcache -expand -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/SetDirty +add wave -noupdate -expand -group lsu -expand -group dcache -expand -group SRAM-update-control /testbench/dut/core/lsu/bus/dcache/dcache/ClearDirty +add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {requesting address} /testbench/dut/core/lsu/IEUAdrE +add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {requesting address} /testbench/dut/core/lsu/bus/dcache/dcache/PAdr add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/ReadDataLineWay add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/ReadDataLineCache add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/TagWay add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/Tag add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/ValidWay add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/HitWay -add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs -color {Blue Violet} /testbench/dut/core/lsu/bus/dcache/dcache/CacheHit add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/DirtyWay add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/Dirty} add wave -noupdate -expand -group lsu -expand -group dcache -group SRAM-outputs /testbench/dut/core/lsu/bus/dcache/dcache/HitDirtyWay @@ -294,7 +311,6 @@ add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM w add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} /testbench/dut/core/lsu/bus/dcache/dcache/SetDirty add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} /testbench/dut/core/lsu/bus/dcache/dcache/ClearDirty add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} /testbench/dut/core/lsu/bus/dcache/dcache/LineByteMask -add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way0 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/SelData} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way0 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/SelectedWriteWordEn} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way0 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/SetValidWay} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way0 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/ClearValidWay} @@ -316,7 +332,6 @@ add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM w add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way0 -expand -group Way0Word3 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/word[3]/wordram/CacheDataMem/bwe} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -expand -group way0 -expand -group Way0Word3 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[0]/word[3]/wordram/CacheDataMem/RAM} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[1]/SelNonHit} -add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[1]/SelData} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[1]/SelectedWriteWordEn} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[1]/SetValidWay} add wave -noupdate -expand -group lsu -expand -group dcache -group {Cache SRAM writes} -group way1 {/testbench/dut/core/lsu/bus/dcache/dcache/CacheWays[1]/ClearValidWay} @@ -410,30 +425,29 @@ add wave -noupdate -expand -group lsu -group pma /testbench/dut/core/lsu/dmmu/dm add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dmmu/PMPInstrAccessFaultF add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dmmu/PMPLoadAccessFaultM add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dmmu/PMPStoreAmoAccessFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/SelHPTW -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/HPTWStall -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/DTLBWalk -add wave -noupdate -expand -group lsu -expand -group ptwalker -color Gold /testbench/dut/core/lsu/hptw/hptw/WalkerState -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/NextWalkerState -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/HPTWAdr -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/PTE -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/NextPageType -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/PageType -add wave -noupdate -expand -group lsu -expand -group ptwalker /testbench/dut/core/lsu/hptw/hptw/ValidNonLeafPTE -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group types /testbench/dut/core/lsu/ITLBMissF -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group types /testbench/dut/core/lsu/DTLBMissM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group types /testbench/dut/core/lsu/hptw/hptw/ITLBWriteF -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group types /testbench/dut/core/lsu/hptw/hptw/DTLBWriteM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/HPTWFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LSUAccessFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/DCacheStallM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/HPTWInstrAccessFaultF -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LSULoadAccessFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LSUStoreAmoAccessFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LoadAccessFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/StoreAmoAccessFaultM -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/HPTWInstrAccessFault -add wave -noupdate -expand -group lsu -expand -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/PBMTFaultM +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/SelHPTW +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/HPTWStall +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/DTLBWalk +add wave -noupdate -expand -group lsu -group ptwalker -color Gold /testbench/dut/core/lsu/hptw/hptw/WalkerState +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/NextWalkerState +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/HPTWAdr +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/PTE +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/NextPageType +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/PageType +add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/hptw/hptw/ValidNonLeafPTE +add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/ITLBMissF +add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/DTLBMissM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/hptw/hptw/ITLBWriteF +add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/hptw/hptw/DTLBWriteM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/HPTWFaultM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LSUAccessFaultM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/HPTWInstrAccessFaultF +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LSULoadAccessFaultM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LSUStoreAmoAccessFaultM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/LoadAccessFaultM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/StoreAmoAccessFaultM +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/HPTWInstrAccessFault +add wave -noupdate -expand -group lsu -group ptwalker -expand -group faults /testbench/dut/core/lsu/hptw/hptw/PBMTFaultM add wave -noupdate -group {WriteBack stage} /testbench/InstrW add wave -noupdate -group {WriteBack stage} /testbench/InstrWName add wave -noupdate -group {WriteBack stage} /testbench/dut/core/priv/priv/pmd/wfiW @@ -665,9 +679,31 @@ add wave -noupdate -group wfi /testbench/dut/core/priv/priv/pmd/WFITimeoutM add wave -noupdate -expand -group testbench /testbench/DCacheFlushStart add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFaultDelay +add wave -noupdate /testbench/dut/GPRWen +add wave -noupdate /testbench/dut/FPRWen +add wave -noupdate /testbench/dut/GPRAdr +add wave -noupdate /testbench/dut/FPRValue +add wave -noupdate /testbench/dut/GPRValue001 +add wave -noupdate /testbench/dut/FPRAdr +add wave -noupdate /testbench/dut/Registers +add wave -noupdate /testbench/dut/PCW +add wave -noupdate /testbench/dut/InstrW +add wave -noupdate /testbench/dut/Mcycle +add wave -noupdate /testbench/dut/Minstret +add wave -noupdate /testbench/dut/TrapW +add wave -noupdate /testbench/dut/PrivilegeModeW +add wave -noupdate /testbench/dut/Required +add wave -noupdate /testbench/dut/rvvisynth/NumCSRs +add wave -noupdate /testbench/dut/rvvisynth/CSRAdr0 +add wave -noupdate /testbench/dut/rvvisynth/CSRData0 +add wave -noupdate /testbench/dut/rvvisynth/CSRData1 +add wave -noupdate /testbench/dut/rvvisynth/CSRAdr2 +add wave -noupdate /testbench/dut/rvvisynth/CSRData2 +add wave -noupdate /testbench/dut/rvvisynth/CSRs +add wave -noupdate /testbench/dut/rvvisynth/valid TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 4} {6586 ns} 1} {{Cursor 4} {11656 ns} 0} {{Cursor 3} {403021 ns} 1} -quietly wave cursor active 2 +WaveRestoreCursors {{Cursor 4} {2298495 ns} 0} {{Cursor 4} {69146 ns} 1} {{Cursor 3} {403021 ns} 1} +quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 194 configure wave -justifyvalue left @@ -682,4 +718,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {11566 ns} {11760 ns} +WaveRestoreZoom {2298408 ns} {2298612 ns} diff --git a/src/wally/csrindextoaddr.sv b/src/wally/csrindextoaddr.sv index e06508bdf..8b2d9e6b7 100644 --- a/src/wally/csrindextoaddr.sv +++ b/src/wally/csrindextoaddr.sv @@ -27,12 +27,12 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -module csrindextoaddr #(parameter NUM_CSRS = 36) ( - input logic [ROWS-1:0] CSRWen, +module csrindextoaddr #(parameter TOTAL_CSRS = 36) ( + input logic [TOTAL_CSRS-1:0] CSRWen, output logic [11:0] CSRAddr); always_comb begin - case(CSRWen) begin + case(CSRWen) 36'h0_0000_0000: CSRAddr = 13'h000; 36'h0_0000_0001: CSRAddr = 13'h300; 36'h0_0000_0002: CSRAddr = 13'h310; @@ -71,7 +71,7 @@ module csrindextoaddr #(parameter NUM_CSRS = 36) ( 36'h4_0000_0000: CSRAddr = 13'h002; 36'h8_0000_0000: CSRAddr = 13'h003; default : CSRAddr = 13'h000; - end + endcase end endmodule diff --git a/src/wally/priorityaomux.sv b/src/wally/priorityaomux.sv index c99b0e1ed..d542c946f 100644 --- a/src/wally/priorityaomux.sv +++ b/src/wally/priorityaomux.sv @@ -33,7 +33,6 @@ module priorityaomux #(parameter ROWS = 8, COLS = 64) ( output logic [COLS-1:0] Y, output logic [ROWS-1:0] SelPriority); - logic [ROWS-1:0] SelPriority; logic [COLS-1:0] AMasked [ROWS-1:0]; genvar index; diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv index 019000915..1bdc627d8 100644 --- a/src/wally/rvvisynth.sv +++ b/src/wally/rvvisynth.sv @@ -31,7 +31,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, parameter integer MAX_CSRS)( input logic clk, reset, output logic valid, - output logic [163+P.XLEN-1:0] Requied, + output logic [163+P.XLEN-1:0] Required, output logic [12+2*P.XLEN-1:0] Registers, output logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs ); @@ -54,9 +54,10 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [P.XLEN-1:0] XLENZeros; logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; logic [TOTAL_CSRS-1:0] CSRArrayWen; - logic [MAX_CSRS-1:0] CSRValue [P.XLEN-1:0]; - logic [MAX_CSRS-1:0] CSRWen [TOTAL_CSRS-1:0]; - logic [MAX_CSRS-1:0] CSRAddr [11:0]; + logic [P.XLEN-1:0] CSRValue [MAX_CSRS-1:0]; + logic [TOTAL_CSRS-1:0] CSRWen [MAX_CSRS-1:0]; + logic [11:0] CSRAddr [MAX_CSRS-1:0]; + logic [MAX_CSRS-1:0] EnabledCSRs; // get signals from the core. assign StallW = testbench.dut.core.StallW; @@ -147,14 +148,14 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, // step 3a for(index = 0; index < MAX_CSRS; index = index + 1) begin - logic [NUM_CSRS-index-1:0] CSRWenShort; - priorityaomux #(NUM_CSRS-index, P.XLEN) priorityaomux(CSRArrayWen[MAX_CSRS-1:index], CSRArray[MAX_CSRS-1:index], CSRValue[index], CSRWenShort); + logic [MAX_CSRS-index-1:0] CSRWenShort; + priorityaomux #(MAX_CSRS-index, P.XLEN) priorityaomux(CSRArrayWen[MAX_CSRS-1:index], CSRArray[MAX_CSRS-1:index], CSRValue[index], CSRWenShort); assign CSRWen[index] = {{{index}{1'b0}}, CSRWenShort}; // step 3b - csrindextoaddr #(NUM_CSRS) csrindextoaddr(CSRWen, CSRAddr); - assign CSRs[(index+1) * P.XLEN - 1 + 12 + 12: index * P.XLEN + 12] = {CSRValue[index], CSRAddr[index]}; + csrindextoaddr #(TOTAL_CSRS) csrindextoaddr(CSRWen[index], CSRAddr[index]); + assign CSRs[(index+1) * (P.XLEN + 12) + 12 - 1: index * (P.XLEN + 12) + 12] = {CSRValue[index], CSRAddr[index]}; + assign EnabledCSRs[index] = |CSRWenShort; end - - + assign CSRs[11:0] = +EnabledCSRs; endmodule diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index d82a5c0d4..5b359eedf 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -87,4 +87,12 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS); end + + localparam MAX_CSRS = 3; + logic valid; + logic [163+P.XLEN-1:0] Required; + logic [12+2*P.XLEN-1:0] Registers; + logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs; + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .Required, .Registers, .CSRs); + endmodule From ea5d780adf50f78b9ebe06a02c3c6248372e07e0 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 21 May 2024 12:42:43 -0500 Subject: [PATCH 005/163] Closer to synthesized rvvi --- src/wally/rvvisynth.sv | 28 +++++++++++++++++----------- src/wally/wallypipelinedsoc.sv | 6 ++---- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv index 1bdc627d8..a8c3a608c 100644 --- a/src/wally/rvvisynth.sv +++ b/src/wally/rvvisynth.sv @@ -31,15 +31,13 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, parameter integer MAX_CSRS)( input logic clk, reset, output logic valid, - output logic [163+P.XLEN-1:0] Required, - output logic [12+2*P.XLEN-1:0] Registers, - output logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs + output logic [199+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi ); localparam TOTAL_CSRS = 36; // pipeline controlls - logic StallW, FlushW; + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; // required logic [P.XLEN-1:0] PCM, PCW; logic InstrValidM, InstrValidW; @@ -58,9 +56,17 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [TOTAL_CSRS-1:0] CSRWen [MAX_CSRS-1:0]; logic [11:0] CSRAddr [MAX_CSRS-1:0]; logic [MAX_CSRS-1:0] EnabledCSRs; + logic [11:0] CSRCount; + logic [177+P.XLEN-1:0] Required; + logic [10+2*P.XLEN-1:0] Registers; + logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. + assign StallE = testbench.dut.core.StallE; + assign StallM = testbench.dut.core.StallM; assign StallW = testbench.dut.core.StallW; + assign FlushE = testbench.dut.core.FlushE; + assign FlushM = testbench.dut.core.FlushM; assign FlushW = testbench.dut.core.FlushW; assign InstrValidM = testbench.dut.core.ieu.InstrValidM; assign InstrRawD = testbench.dut.core.ifu.InstrRawD; @@ -129,11 +135,11 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW); assign valid = InstrValidW & ~StallW; - assign Required = {PrivilegeModeW, TrapW, Minstret, Mcycle, InstrRawW, PCW}; - assign Registers = {FPRWen, GPRWen} == 2'b11 ? {FPRValue, FPRAddr, GPRValue, GPRAddr, FPRWen, GPRWen} : - {FPRWen, GPRWen} == 2'b01 ? {XLENZeros, 5'b0, GPRValue, GPRAddr, FPRWen, GPRWen} : - {FPRWen, GPRWen} == 2'b10 ? {FPRValue, FPRAddr, XLENZeros, 5'b0, FPRWen, GPRWen} : - {XLENZeros, 5'b0, XLENZeros, 5'b0, FPRWen, GPRWen}; + assign Required = {CSRCount, FPRWen, GPRWen, PrivilegeModeW, TrapW, Minstret, Mcycle, InstrRawW, PCW}; + assign Registers = {FPRWen, GPRWen} == 2'b11 ? {FPRValue, FPRAddr, GPRValue, GPRAddr} : + {FPRWen, GPRWen} == 2'b01 ? {XLENZeros, 5'b0, GPRValue, GPRAddr} : + {FPRWen, GPRWen} == 2'b10 ? {XLENZeros, 5'b0, FPRValue, FPRAddr} : + '0; // the CSRs are complex // 1. we need to get the CSR values @@ -153,9 +159,9 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRWen[index] = {{{index}{1'b0}}, CSRWenShort}; // step 3b csrindextoaddr #(TOTAL_CSRS) csrindextoaddr(CSRWen[index], CSRAddr[index]); - assign CSRs[(index+1) * (P.XLEN + 12) + 12 - 1: index * (P.XLEN + 12) + 12] = {CSRValue[index], CSRAddr[index]}; + assign CSRs[(index+1) * (P.XLEN + 12)- 1: index * (P.XLEN + 12)] = {CSRValue[index], CSRAddr[index]}; assign EnabledCSRs[index] = |CSRWenShort; end - assign CSRs[11:0] = +EnabledCSRs; + assign CSRCount = +EnabledCSRs; endmodule diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 63f10549c..1d4680e30 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -93,9 +93,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( localparam MAX_CSRS = 3; logic valid; - logic [163+P.XLEN-1:0] Required; - logic [12+2*P.XLEN-1:0] Registers; - logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs; - rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .Required, .Registers, .CSRs); + logic [199+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); endmodule From 8fd278b322b7a8a47ab20db4046ebf74a3bd6969 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 21 May 2024 16:15:05 -0500 Subject: [PATCH 006/163] Fixed some references to rvvi. --- src/wally/rvvisynth.sv | 106 +++++++++++++++++---------------- src/wally/wallypipelinedsoc.sv | 2 +- 2 files changed, 55 insertions(+), 53 deletions(-) diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv index a8c3a608c..27a1fe6d3 100644 --- a/src/wally/rvvisynth.sv +++ b/src/wally/rvvisynth.sv @@ -31,7 +31,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, parameter integer MAX_CSRS)( input logic clk, reset, output logic valid, - output logic [199+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi + output logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi ); localparam TOTAL_CSRS = 36; @@ -59,67 +59,67 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [11:0] CSRCount; logic [177+P.XLEN-1:0] Required; logic [10+2*P.XLEN-1:0] Registers; - logic [12+MAX_CSRS*(P.XLEN+12)-1:0] CSRs; + logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. - assign StallE = testbench.dut.core.StallE; - assign StallM = testbench.dut.core.StallM; - assign StallW = testbench.dut.core.StallW; - assign FlushE = testbench.dut.core.FlushE; - assign FlushM = testbench.dut.core.FlushM; - assign FlushW = testbench.dut.core.FlushW; - assign InstrValidM = testbench.dut.core.ieu.InstrValidM; - assign InstrRawD = testbench.dut.core.ifu.InstrRawD; - assign PCM = testbench.dut.core.ifu.PCM; - assign Mcycle = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = testbench.dut.core.TrapM; - assign PrivilegeModeW = testbench.dut.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = testbench.dut.core.ieu.dp.regf.a3; - assign GPRWen = testbench.dut.core.ieu.dp.regf.we3; - assign GPRValue = testbench.dut.core.ieu.dp.regf.wd3; - assign FPRAddr = testbench.dut.core.fpu.fpu.fregfile.a4; - assign FPRWen = testbench.dut.core.fpu.fpu.fregfile.we4; - assign FPRValue = testbench.dut.core.fpu.fpu.fregfile.wd4; + assign StallE = dut.core.StallE; + assign StallM = dut.core.StallM; + assign StallW = dut.core.StallW; + assign FlushE = dut.core.FlushE; + assign FlushM = dut.core.FlushM; + assign FlushW = dut.core.FlushW; + assign InstrValidM = dut.core.ieu.InstrValidM; + assign InstrRawD = dut.core.ifu.InstrRawD; + assign PCM = dut.core.ifu.PCM; + assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = dut.core.TrapM; + assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = dut.core.ieu.dp.regf.a3; + assign GPRWen = dut.core.ieu.dp.regf.we3; + assign GPRValue = dut.core.ieu.dp.regf.wd3; + assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; - assign CSRArray[0] = testbench.dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = testbench.dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = testbench.dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = testbench.dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = testbench.dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = testbench.dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = testbench.dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = testbench.dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = testbench.dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = testbench.dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 assign CSRArray[16] = 0; // 12'hF11 assign CSRArray[17] = 0; // 12'hF12 assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 assign CSRArray[19] = 0; // 12'hF15 assign CSRArray[20] = 0; // 12'h34A // supervisor CSRs - assign CSRArray[21] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = testbench.dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = testbench.dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = testbench.dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = testbench.dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D // user CSRs - assign CSRArray[33] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW, testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 // assign XLENZeros = '0; @@ -163,5 +163,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign EnabledCSRs[index] = |CSRWenShort; end assign CSRCount = +EnabledCSRs; + assign rvvi = {CSRs, Registers, Required}; + endmodule diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 1d4680e30..a5dbe0a87 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -93,7 +93,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( localparam MAX_CSRS = 3; logic valid; - logic [199+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); endmodule From d1141237eee01f8eadbf0cd7e5892b7021dfa9bf Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 21 May 2024 16:20:53 -0500 Subject: [PATCH 007/163] Removed prefix from rvvi hierarchy so it works without testbench. --- src/wally/rvvisynth.sv | 100 ++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/wally/rvvisynth.sv b/src/wally/rvvisynth.sv index 27a1fe6d3..e5801cf09 100644 --- a/src/wally/rvvisynth.sv +++ b/src/wally/rvvisynth.sv @@ -62,64 +62,64 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. - assign StallE = dut.core.StallE; - assign StallM = dut.core.StallM; - assign StallW = dut.core.StallW; - assign FlushE = dut.core.FlushE; - assign FlushM = dut.core.FlushM; - assign FlushW = dut.core.FlushW; - assign InstrValidM = dut.core.ieu.InstrValidM; - assign InstrRawD = dut.core.ifu.InstrRawD; - assign PCM = dut.core.ifu.PCM; - assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = dut.core.TrapM; - assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = dut.core.ieu.dp.regf.a3; - assign GPRWen = dut.core.ieu.dp.regf.we3; - assign GPRValue = dut.core.ieu.dp.regf.wd3; - assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; - assign FPRWen = dut.core.fpu.fpu.fregfile.we4; - assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; + assign StallE = core.StallE; + assign StallM = core.StallM; + assign StallW = core.StallW; + assign FlushE = core.FlushE; + assign FlushM = core.FlushM; + assign FlushW = core.FlushW; + assign InstrValidM = core.ieu.InstrValidM; + assign InstrRawD = core.ifu.InstrRawD; + assign PCM = core.ifu.PCM; + assign Mcycle = core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = core.TrapM; + assign PrivilegeModeW = core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = core.ieu.dp.regf.a3; + assign GPRWen = core.ieu.dp.regf.we3; + assign GPRValue = core.ieu.dp.regf.wd3; + assign FPRAddr = core.fpu.fpu.fregfile.a4; + assign FPRWen = core.fpu.fpu.fregfile.we4; + assign FPRValue = core.fpu.fpu.fregfile.wd4; - assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[0] = core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 assign CSRArray[16] = 0; // 12'hF11 assign CSRArray[17] = 0; // 12'hF12 assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 assign CSRArray[19] = 0; // 12'hF15 assign CSRArray[20] = 0; // 12'h34A // supervisor CSRs - assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + assign CSRArray[21] = core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D // user CSRs - assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + assign CSRArray[33] = core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {core.priv.priv.csr.csru.csru.FRM_REGW, core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 // assign XLENZeros = '0; From b116c0c9024059390ce75f97df8584a2911f7ae3 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 21 May 2024 18:23:42 -0500 Subject: [PATCH 008/163] Lots of progress on the rvvisynth to ethernet packetizer. Almost producing axi4 commands. --- src/wally/packetizer.sv | 153 +++++++++++++++++++++++++++++++++ src/wally/wallypipelinedsoc.sv | 51 +++++++++++ 2 files changed, 204 insertions(+) create mode 100644 src/wally/packetizer.sv diff --git a/src/wally/packetizer.sv b/src/wally/packetizer.sv new file mode 100644 index 000000000..8df53c1bf --- /dev/null +++ b/src/wally/packetizer.sv @@ -0,0 +1,153 @@ +/////////////////////////////////////////// +// packetizer.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: 21 May 2024 +// Modified: 21 May 2024 +// +// Purpose: Converts the compressed RVVI format into AXI 4 burst write transactions. +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module packetizer import cvw::*; #(parameter cvw_t P, + parameter integer MAX_CSRS)( + input logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi, + input logic valid, + input logic m_axi_aclk, m_axi_aresetn, + output logic RVVIStall, + // axi 4 write address channel + output logic [3:0] m_axi_awid, + output logic [12:0] m_axi_awaddr, + output logic [7:0] m_axi_awlen, + output logic [2:0] m_axi_awsize, + output logic [1:0] m_axi_awburst, + output logic [3:0] m_axi_awcache, + output logic m_axi_awvalid, + input logic m_axi_awready, + // axi 4 write data channel + output logic [31:0] m_axi_wdata, + output logic [3:0] m_axi_wstrb, + output logic m_axi_wlast, + output logic m_axi_wvalid, + input logic m_axi_wready, + // axi 4 write response channel + input logic [3:0] m_axi_bid, + input logic [1:0] m_axi_bresp, + input logic m_axi_bvalid, + output logic m_axi_bready, + // axi 4 read address channel + output logic [3:0] m_axi_arid, + output logic [12:0] m_axi_araddr, + output logic [7:0] m_axi_arlen, + output logic [2:0] m_axi_arsize, + output logic [1:0] m_axi_arburst, + output logic [3:0] m_axi_arcache, + output logic m_axi_arvalid, + input logic m_axi_arready, + // axi 4 read data channel + input logic [3:0] m_axi_rid, + input logic [31:0] m_axi_rdata, + input logic [1:0] m_axi_rresp, + input logic m_axi_rlast, + input logic m_axi_rvalid, + output logic m_axi_rready + ); + + localparam TotalFrameLengthBits = 2*48+32+16+187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12); + localparam TotalFrameLengthBytes = TotalFrameLengthBits / 8; + + logic [9:0] WordCount; + logic [11:0] BytesInFrame; + logic TransReady; + logic BurstDone; + logic WordCountReset; + logic WordCountEnable; + logic [47:0] SrcMac, DstMac; + logic [31:0] Tag; + logic [15:0] Length; + logic [TotalFrameLengthBits-1:0] TotalFrame; + logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; + + typedef enum {STATE_RDY, STATE_WAIT, STATE_TRANS, STATE_TRANS_DONE} statetype; + statetype CurrState, NextState; + + always_ff @(posedge m_axi_aclk) begin + if(~m_axi_aresetn) CurrState <= STATE_RDY; + else CurrState <= NextState; + end + + always_comb begin + case(CurrState) + STATE_RDY: if (TransReady & valid) NextState = STATE_TRANS; + else if(~TransReady & valid) NextState = STATE_WAIT; + STATE_WAIT: if(TransReady) NextState = STATE_TRANS; + else NextState = STATE_WAIT; + STATE_TRANS: if(BurstDone) NextState = STATE_RDY; + else NextState = STATE_TRANS; + default: NextState = STATE_RDY; + endcase + end + + assign RVVIStall = CurrState != STATE_RDY; + assign TransReady = m_axi_awready & m_axi_wready; + assign WordCountEnable = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS & TransReady); + assign WordCountReset = CurrState == STATE_RDY; + + + counter #(10) WordCounter(m_axi_aclk, WordCountReset, WordCountEnable, WordCount); + // *** BUG BytesInFrame will eventually depend on the length of the data stored into the ethernet frame + // for now this will be exactly 608 bits (76 bytes, 19 words) + assign BytesInFrame = 12'd76; + assign BurstDone = WordCount == BytesInFrame[11:2]; + + assign m_axi_awid = '0; + assign m_axi_awaddr = '0; // *** bug update to be based on the correct address during each beat. + assign m_axi_awlen = BytesInFrame[11:2]; + assign m_axi_awsize = 3'b010; // 4 bytes + assign m_axi_awburst = 2'b01; // increment + assign m_axi_awcache = '0; + assign m_axi_awvalid = (CurrState == STATE_RDY & valid) | CurrState == STATE_TRANS; + genvar index; + for (index = 0; index < TotalFrameLengthBytes/4; index++) begin + assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; + end + + assign TotalFrame = {rvvi, Length, Tag, DstMac, SrcMac}; + + // *** fix me later + assign SrcMac = '0; + assign DstMac = '0; + assign Tag = '0; + assign Length = BytesInFrame + 16'd6 + 16'd6 + 16'd4 + 16'd2; + + assign m_axi_wdata = TotalFrameWords[WordCount]; + assign m_axi_wstrb = '1; + assign m_axi_wlast = BurstDone; + assign m_axi_wvalid = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS); + + + assign m_axi_bready = 1'b1; // *** probably wrong. + + // we aren't using the read channels. This ethernet device isn't going to read anything for now + assign {m_axi_arid, m_axi_araddr, m_axi_arlen, m_axi_arsize, m_axi_arburst, m_axi_arcache, m_axi_arvalid, m_axi_rready} = '0; + +endmodule + diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index a5dbe0a87..d2cf7226e 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -95,5 +95,56 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic valid; logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); + + logic [3:0] m_axi_awid; + logic [12:0] m_axi_awaddr; + logic [7:0] m_axi_awlen; + logic [2:0] m_axi_awsize; + logic [1:0] m_axi_awburst; + logic [3:0] m_axi_awcache; + logic m_axi_awvalid; + logic m_axi_awready; + // axi 4 write data channel + logic [31:0] m_axi_wdata; + logic [3:0] m_axi_wstrb; + logic m_axi_wlast; + logic m_axi_wvalid; + logic m_axi_wready; + // axi 4 write response channel + logic [3:0] m_axi_bid; + logic [1:0] m_axi_bresp; + logic m_axi_bvalid; + logic m_axi_bready; + // axi 4 read address channel + logic [3:0] m_axi_arid; + logic [12:0] m_axi_araddr; + logic [7:0] m_axi_arlen; + logic [2:0] m_axi_arsize; + logic [1:0] m_axi_arburst; + logic [3:0] m_axi_arcache; + logic m_axi_arvalid; + logic m_axi_arready; + // axi 4 read data channel + logic [3:0] m_axi_rid; + logic [31:0] m_axi_rdata; + logic [1:0] m_axi_rresp; + logic m_axi_rlast; + logic m_axi_rvalid; + logic m_axi_rready; + + + + logic RVVIStall; + + packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, + .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, + .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready, .m_axi_bid, + .m_axi_bresp, .m_axi_bvalid, .m_axi_bready, .m_axi_arid, .m_axi_araddr, .m_axi_arlen, .m_axi_arsize, + .m_axi_arburst, .m_axi_arcache, .m_axi_arvalid, .m_axi_arready, .m_axi_rid, .m_axi_rdata, .m_axi_rresp, + .m_axi_rlast, .m_axi_rvalid, .m_axi_rready); + + // *** finally fake the axi4 interface + assign m_axi_awready = '1; + assign m_axi_wready = '1; endmodule From e5b8fd35b0d9007e60d260d25a7991feefe3dbc1 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 22 May 2024 09:56:12 -0500 Subject: [PATCH 009/163] Successfully added RVVIStall for back pressure to slow down the pipeline if the ethernet or host computer running imperasDV can't keep up. --- src/hazard/hazard.sv | 4 ++-- src/wally/packetizer.sv | 1 - src/wally/wallypipelinedcore.sv | 5 +++-- src/wally/wallypipelinedsoc.sv | 12 +++++++----- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index 5d2611dda..ed3b6da3a 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -31,7 +31,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, input logic StructuralStallD, input logic LSUStallM, IFUStallF, - input logic FPUStallD, + input logic FPUStallD, RVVIStall, input logic DivBusyE, FDivBusyE, input logic wfiM, IntPendingM, // Stall & flush outputs @@ -89,7 +89,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1. // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. - assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause); + assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | RVVIStall; // Stall each stage for cause or if the next stage is stalled // coverage off: StallFCause is always 0 diff --git a/src/wally/packetizer.sv b/src/wally/packetizer.sv index 8df53c1bf..4dc68dcab 100644 --- a/src/wally/packetizer.sv +++ b/src/wally/packetizer.sv @@ -143,7 +143,6 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign m_axi_wlast = BurstDone; assign m_axi_wvalid = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS); - assign m_axi_bready = 1'b1; // *** probably wrong. // we aren't using the read channels. This ethernet device isn't going to read anything for now diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 9cc6686fc..335f8cfb9 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -44,7 +44,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( output logic [2:0] HBURST, output logic [3:0] HPROT, output logic [1:0] HTRANS, - output logic HMASTLOCK + output logic HMASTLOCK, + input logic RVVIStall ); logic StallF, StallD, StallE, StallM, StallW; @@ -274,7 +275,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .StructuralStallD, .LSUStallM, .IFUStallF, - .FPUStallD, + .FPUStallD, .RVVIStall, .DivBusyE, .FDivBusyE, .wfiM, .IntPendingM, // Stall & flush outputs diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index d2cf7226e..aaf52f550 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -68,6 +68,11 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic [63:0] MTIME_CLINT; // from CLINT to CSRs logic MExtInt,SExtInt; // from PLIC + localparam MAX_CSRS = 3; + logic valid; + logic RVVIStall; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + // synchronize reset to SOC clock domain synchronizer resetsync(.clk, .d(reset_ext), .q(reset)); @@ -75,7 +80,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( wallypipelinedcore #(P) core(.clk, .reset, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, - .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK + .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .RVVIStall ); // instantiate uncore if a bus interface exists @@ -91,9 +96,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( end - localparam MAX_CSRS = 3; - logic valid; - logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); logic [3:0] m_axi_awid; @@ -134,7 +137,6 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( - logic RVVIStall; packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, From bf9f45d31974fc69dc88ff4c923d8547f843e519 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 11:25:42 -0500 Subject: [PATCH 010/163] We have a simulation of the ethernet transmission working. This commit does not include the source files for the ethernet as it does not belong to cvw. I'll want to fork that repo and make it a submodule as I need to change the source a bit. --- sim/questa/wave.do | 62 +++++++++---------------------- src/{wally => rvvi}/packetizer.sv | 8 ++-- src/{wally => rvvi}/rvvisynth.sv | 0 src/wally/wallypipelinedsoc.sv | 34 +++++++++++++++-- 4 files changed, 53 insertions(+), 51 deletions(-) rename src/{wally => rvvi}/packetizer.sv (96%) rename src/{wally => rvvi}/rvvisynth.sv (100%) diff --git a/sim/questa/wave.do b/sim/questa/wave.do index d4d9f8f95..a1ae5fe8f 100644 --- a/sim/questa/wave.do +++ b/sim/questa/wave.do @@ -1,25 +1,5 @@ onerror {resume} quietly virtual signal -install /testbench/dut/core/ifu/bpred/bpred { /testbench/dut/core/ifu/bpred/bpred/PostSpillInstrRawF[11:7]} rd -quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[11], /testbench/dut/rvvisynth/CSRs[10], /testbench/dut/rvvisynth/CSRs[9], /testbench/dut/rvvisynth/CSRs[8], /testbench/dut/rvvisynth/CSRs[7], /testbench/dut/rvvisynth/CSRs[6], /testbench/dut/rvvisynth/CSRs[5], /testbench/dut/rvvisynth/CSRs[4], /testbench/dut/rvvisynth/CSRs[3], /testbench/dut/rvvisynth/CSRs[2], /testbench/dut/rvvisynth/CSRs[1], /testbench/dut/rvvisynth/CSRs[0] }} NumCSRs -quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[23], /testbench/dut/rvvisynth/CSRs[22], /testbench/dut/rvvisynth/CSRs[21], /testbench/dut/rvvisynth/CSRs[20], /testbench/dut/rvvisynth/CSRs[19], /testbench/dut/rvvisynth/CSRs[18], /testbench/dut/rvvisynth/CSRs[17], /testbench/dut/rvvisynth/CSRs[16], /testbench/dut/rvvisynth/CSRs[15], /testbench/dut/rvvisynth/CSRs[14], /testbench/dut/rvvisynth/CSRs[13], /testbench/dut/rvvisynth/CSRs[12] }} CSRAdr0 -quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[87], /testbench/dut/rvvisynth/CSRs[86], /testbench/dut/rvvisynth/CSRs[85], /testbench/dut/rvvisynth/CSRs[84], /testbench/dut/rvvisynth/CSRs[83], /testbench/dut/rvvisynth/CSRs[82], /testbench/dut/rvvisynth/CSRs[81], /testbench/dut/rvvisynth/CSRs[80], /testbench/dut/rvvisynth/CSRs[79], /testbench/dut/rvvisynth/CSRs[78], /testbench/dut/rvvisynth/CSRs[77], /testbench/dut/rvvisynth/CSRs[76], /testbench/dut/rvvisynth/CSRs[75], /testbench/dut/rvvisynth/CSRs[74], /testbench/dut/rvvisynth/CSRs[73], /testbench/dut/rvvisynth/CSRs[72], /testbench/dut/rvvisynth/CSRs[71], /testbench/dut/rvvisynth/CSRs[70], /testbench/dut/rvvisynth/CSRs[69], /testbench/dut/rvvisynth/CSRs[68], /testbench/dut/rvvisynth/CSRs[67], /testbench/dut/rvvisynth/CSRs[66], /testbench/dut/rvvisynth/CSRs[65], /testbench/dut/rvvisynth/CSRs[64], /testbench/dut/rvvisynth/CSRs[63], /testbench/dut/rvvisynth/CSRs[62], /testbench/dut/rvvisynth/CSRs[61], /testbench/dut/rvvisynth/CSRs[60], /testbench/dut/rvvisynth/CSRs[59], /testbench/dut/rvvisynth/CSRs[58], /testbench/dut/rvvisynth/CSRs[57], /testbench/dut/rvvisynth/CSRs[56], /testbench/dut/rvvisynth/CSRs[55], /testbench/dut/rvvisynth/CSRs[54], /testbench/dut/rvvisynth/CSRs[53], /testbench/dut/rvvisynth/CSRs[52], /testbench/dut/rvvisynth/CSRs[51], /testbench/dut/rvvisynth/CSRs[50], /testbench/dut/rvvisynth/CSRs[49], /testbench/dut/rvvisynth/CSRs[48], /testbench/dut/rvvisynth/CSRs[47], /testbench/dut/rvvisynth/CSRs[46], /testbench/dut/rvvisynth/CSRs[45], /testbench/dut/rvvisynth/CSRs[44], /testbench/dut/rvvisynth/CSRs[43], /testbench/dut/rvvisynth/CSRs[42], /testbench/dut/rvvisynth/CSRs[41], /testbench/dut/rvvisynth/CSRs[40], /testbench/dut/rvvisynth/CSRs[39], /testbench/dut/rvvisynth/CSRs[38], /testbench/dut/rvvisynth/CSRs[37], /testbench/dut/rvvisynth/CSRs[36], /testbench/dut/rvvisynth/CSRs[35], /testbench/dut/rvvisynth/CSRs[34], /testbench/dut/rvvisynth/CSRs[33], /testbench/dut/rvvisynth/CSRs[32], /testbench/dut/rvvisynth/CSRs[31], /testbench/dut/rvvisynth/CSRs[30], /testbench/dut/rvvisynth/CSRs[29], /testbench/dut/rvvisynth/CSRs[28], /testbench/dut/rvvisynth/CSRs[27], /testbench/dut/rvvisynth/CSRs[26], /testbench/dut/rvvisynth/CSRs[25], /testbench/dut/rvvisynth/CSRs[24] }} CSRData0 -quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[163], /testbench/dut/rvvisynth/CSRs[162], /testbench/dut/rvvisynth/CSRs[161], /testbench/dut/rvvisynth/CSRs[160], /testbench/dut/rvvisynth/CSRs[159], /testbench/dut/rvvisynth/CSRs[158], /testbench/dut/rvvisynth/CSRs[157], /testbench/dut/rvvisynth/CSRs[156], /testbench/dut/rvvisynth/CSRs[155], /testbench/dut/rvvisynth/CSRs[154], /testbench/dut/rvvisynth/CSRs[153], /testbench/dut/rvvisynth/CSRs[152], /testbench/dut/rvvisynth/CSRs[151], /testbench/dut/rvvisynth/CSRs[150], /testbench/dut/rvvisynth/CSRs[149], /testbench/dut/rvvisynth/CSRs[148], /testbench/dut/rvvisynth/CSRs[147], /testbench/dut/rvvisynth/CSRs[146], /testbench/dut/rvvisynth/CSRs[145], /testbench/dut/rvvisynth/CSRs[144], /testbench/dut/rvvisynth/CSRs[143], /testbench/dut/rvvisynth/CSRs[142], /testbench/dut/rvvisynth/CSRs[141], /testbench/dut/rvvisynth/CSRs[140], /testbench/dut/rvvisynth/CSRs[139], /testbench/dut/rvvisynth/CSRs[138], /testbench/dut/rvvisynth/CSRs[137], /testbench/dut/rvvisynth/CSRs[136], /testbench/dut/rvvisynth/CSRs[135], /testbench/dut/rvvisynth/CSRs[134], /testbench/dut/rvvisynth/CSRs[133], /testbench/dut/rvvisynth/CSRs[132], /testbench/dut/rvvisynth/CSRs[131], /testbench/dut/rvvisynth/CSRs[130], /testbench/dut/rvvisynth/CSRs[129], /testbench/dut/rvvisynth/CSRs[128], /testbench/dut/rvvisynth/CSRs[127], /testbench/dut/rvvisynth/CSRs[126], /testbench/dut/rvvisynth/CSRs[125], /testbench/dut/rvvisynth/CSRs[124], /testbench/dut/rvvisynth/CSRs[123], /testbench/dut/rvvisynth/CSRs[122], /testbench/dut/rvvisynth/CSRs[121], /testbench/dut/rvvisynth/CSRs[120], /testbench/dut/rvvisynth/CSRs[119], /testbench/dut/rvvisynth/CSRs[118], /testbench/dut/rvvisynth/CSRs[117], /testbench/dut/rvvisynth/CSRs[116], /testbench/dut/rvvisynth/CSRs[115], /testbench/dut/rvvisynth/CSRs[114], /testbench/dut/rvvisynth/CSRs[113], /testbench/dut/rvvisynth/CSRs[112], /testbench/dut/rvvisynth/CSRs[111], /testbench/dut/rvvisynth/CSRs[110], /testbench/dut/rvvisynth/CSRs[109], /testbench/dut/rvvisynth/CSRs[108], /testbench/dut/rvvisynth/CSRs[107], /testbench/dut/rvvisynth/CSRs[106], /testbench/dut/rvvisynth/CSRs[105], /testbench/dut/rvvisynth/CSRs[104], /testbench/dut/rvvisynth/CSRs[103], /testbench/dut/rvvisynth/CSRs[102], /testbench/dut/rvvisynth/CSRs[101], /testbench/dut/rvvisynth/CSRs[100] }} CSRData1 -quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[175], /testbench/dut/rvvisynth/CSRs[174], /testbench/dut/rvvisynth/CSRs[173], /testbench/dut/rvvisynth/CSRs[172], /testbench/dut/rvvisynth/CSRs[171], /testbench/dut/rvvisynth/CSRs[170], /testbench/dut/rvvisynth/CSRs[169], /testbench/dut/rvvisynth/CSRs[168], /testbench/dut/rvvisynth/CSRs[167], /testbench/dut/rvvisynth/CSRs[166], /testbench/dut/rvvisynth/CSRs[165], /testbench/dut/rvvisynth/CSRs[164] }} CSRAdr2 -quietly virtual function -install /testbench/dut/rvvisynth -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/rvvisynth/CSRs[239], /testbench/dut/rvvisynth/CSRs[238], /testbench/dut/rvvisynth/CSRs[237], /testbench/dut/rvvisynth/CSRs[236], /testbench/dut/rvvisynth/CSRs[235], /testbench/dut/rvvisynth/CSRs[234], /testbench/dut/rvvisynth/CSRs[233], /testbench/dut/rvvisynth/CSRs[232], /testbench/dut/rvvisynth/CSRs[231], /testbench/dut/rvvisynth/CSRs[230], /testbench/dut/rvvisynth/CSRs[229], /testbench/dut/rvvisynth/CSRs[228], /testbench/dut/rvvisynth/CSRs[227], /testbench/dut/rvvisynth/CSRs[226], /testbench/dut/rvvisynth/CSRs[225], /testbench/dut/rvvisynth/CSRs[224], /testbench/dut/rvvisynth/CSRs[223], /testbench/dut/rvvisynth/CSRs[222], /testbench/dut/rvvisynth/CSRs[221], /testbench/dut/rvvisynth/CSRs[220], /testbench/dut/rvvisynth/CSRs[219], /testbench/dut/rvvisynth/CSRs[218], /testbench/dut/rvvisynth/CSRs[217], /testbench/dut/rvvisynth/CSRs[216], /testbench/dut/rvvisynth/CSRs[215], /testbench/dut/rvvisynth/CSRs[214], /testbench/dut/rvvisynth/CSRs[213], /testbench/dut/rvvisynth/CSRs[212], /testbench/dut/rvvisynth/CSRs[211], /testbench/dut/rvvisynth/CSRs[210], /testbench/dut/rvvisynth/CSRs[209], /testbench/dut/rvvisynth/CSRs[208], /testbench/dut/rvvisynth/CSRs[207], /testbench/dut/rvvisynth/CSRs[206], /testbench/dut/rvvisynth/CSRs[205], /testbench/dut/rvvisynth/CSRs[204], /testbench/dut/rvvisynth/CSRs[203], /testbench/dut/rvvisynth/CSRs[202], /testbench/dut/rvvisynth/CSRs[201], /testbench/dut/rvvisynth/CSRs[200], /testbench/dut/rvvisynth/CSRs[199], /testbench/dut/rvvisynth/CSRs[198], /testbench/dut/rvvisynth/CSRs[197], /testbench/dut/rvvisynth/CSRs[196], /testbench/dut/rvvisynth/CSRs[195], /testbench/dut/rvvisynth/CSRs[194], /testbench/dut/rvvisynth/CSRs[193], /testbench/dut/rvvisynth/CSRs[192], /testbench/dut/rvvisynth/CSRs[191], /testbench/dut/rvvisynth/CSRs[190], /testbench/dut/rvvisynth/CSRs[189], /testbench/dut/rvvisynth/CSRs[188], /testbench/dut/rvvisynth/CSRs[187], /testbench/dut/rvvisynth/CSRs[186], /testbench/dut/rvvisynth/CSRs[185], /testbench/dut/rvvisynth/CSRs[184], /testbench/dut/rvvisynth/CSRs[183], /testbench/dut/rvvisynth/CSRs[182], /testbench/dut/rvvisynth/CSRs[181], /testbench/dut/rvvisynth/CSRs[180], /testbench/dut/rvvisynth/CSRs[179], /testbench/dut/rvvisynth/CSRs[178], /testbench/dut/rvvisynth/CSRs[177], /testbench/dut/rvvisynth/CSRs[176] }} CSRData2 -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[63], /testbench/dut/Required[62], /testbench/dut/Required[61], /testbench/dut/Required[60], /testbench/dut/Required[59], /testbench/dut/Required[58], /testbench/dut/Required[57], /testbench/dut/Required[56], /testbench/dut/Required[55], /testbench/dut/Required[54], /testbench/dut/Required[53], /testbench/dut/Required[52], /testbench/dut/Required[51], /testbench/dut/Required[50], /testbench/dut/Required[49], /testbench/dut/Required[48], /testbench/dut/Required[47], /testbench/dut/Required[46], /testbench/dut/Required[45], /testbench/dut/Required[44], /testbench/dut/Required[43], /testbench/dut/Required[42], /testbench/dut/Required[41], /testbench/dut/Required[40], /testbench/dut/Required[39], /testbench/dut/Required[38], /testbench/dut/Required[37], /testbench/dut/Required[36], /testbench/dut/Required[35], /testbench/dut/Required[34], /testbench/dut/Required[33], /testbench/dut/Required[32], /testbench/dut/Required[31], /testbench/dut/Required[30], /testbench/dut/Required[29], /testbench/dut/Required[28], /testbench/dut/Required[27], /testbench/dut/Required[26], /testbench/dut/Required[25], /testbench/dut/Required[24], /testbench/dut/Required[23], /testbench/dut/Required[22], /testbench/dut/Required[21], /testbench/dut/Required[20], /testbench/dut/Required[19], /testbench/dut/Required[18], /testbench/dut/Required[17], /testbench/dut/Required[16], /testbench/dut/Required[15], /testbench/dut/Required[14], /testbench/dut/Required[13], /testbench/dut/Required[12], /testbench/dut/Required[11], /testbench/dut/Required[10], /testbench/dut/Required[9], /testbench/dut/Required[8], /testbench/dut/Required[7], /testbench/dut/Required[6], /testbench/dut/Required[5], /testbench/dut/Required[4], /testbench/dut/Required[3], /testbench/dut/Required[2], /testbench/dut/Required[1], /testbench/dut/Required[0] }} PCW -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[95], /testbench/dut/Required[94], /testbench/dut/Required[93], /testbench/dut/Required[92], /testbench/dut/Required[91], /testbench/dut/Required[90], /testbench/dut/Required[89], /testbench/dut/Required[88], /testbench/dut/Required[87], /testbench/dut/Required[86], /testbench/dut/Required[85], /testbench/dut/Required[84], /testbench/dut/Required[83], /testbench/dut/Required[82], /testbench/dut/Required[81], /testbench/dut/Required[80], /testbench/dut/Required[79], /testbench/dut/Required[78], /testbench/dut/Required[77], /testbench/dut/Required[76], /testbench/dut/Required[75], /testbench/dut/Required[74], /testbench/dut/Required[73], /testbench/dut/Required[72], /testbench/dut/Required[71], /testbench/dut/Required[70], /testbench/dut/Required[69], /testbench/dut/Required[68], /testbench/dut/Required[67], /testbench/dut/Required[66], /testbench/dut/Required[65], /testbench/dut/Required[64] }} InstrW -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[159], /testbench/dut/Required[158], /testbench/dut/Required[157], /testbench/dut/Required[156], /testbench/dut/Required[155], /testbench/dut/Required[154], /testbench/dut/Required[153], /testbench/dut/Required[152], /testbench/dut/Required[151], /testbench/dut/Required[150], /testbench/dut/Required[149], /testbench/dut/Required[148], /testbench/dut/Required[147], /testbench/dut/Required[146], /testbench/dut/Required[145], /testbench/dut/Required[144], /testbench/dut/Required[143], /testbench/dut/Required[142], /testbench/dut/Required[141], /testbench/dut/Required[140], /testbench/dut/Required[139], /testbench/dut/Required[138], /testbench/dut/Required[137], /testbench/dut/Required[136], /testbench/dut/Required[135], /testbench/dut/Required[134], /testbench/dut/Required[133], /testbench/dut/Required[132], /testbench/dut/Required[131], /testbench/dut/Required[130], /testbench/dut/Required[129], /testbench/dut/Required[128], /testbench/dut/Required[127], /testbench/dut/Required[126], /testbench/dut/Required[125], /testbench/dut/Required[124], /testbench/dut/Required[123], /testbench/dut/Required[122], /testbench/dut/Required[121], /testbench/dut/Required[120], /testbench/dut/Required[119], /testbench/dut/Required[118], /testbench/dut/Required[117], /testbench/dut/Required[116], /testbench/dut/Required[115], /testbench/dut/Required[114], /testbench/dut/Required[113], /testbench/dut/Required[112], /testbench/dut/Required[111], /testbench/dut/Required[110], /testbench/dut/Required[109], /testbench/dut/Required[108], /testbench/dut/Required[107], /testbench/dut/Required[106], /testbench/dut/Required[105], /testbench/dut/Required[104], /testbench/dut/Required[103], /testbench/dut/Required[102], /testbench/dut/Required[101], /testbench/dut/Required[100], /testbench/dut/Required[99], /testbench/dut/Required[98], /testbench/dut/Required[97], /testbench/dut/Required[96] }} Mcycle -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[223], /testbench/dut/Required[222], /testbench/dut/Required[221], /testbench/dut/Required[220], /testbench/dut/Required[219], /testbench/dut/Required[218], /testbench/dut/Required[217], /testbench/dut/Required[216], /testbench/dut/Required[215], /testbench/dut/Required[214], /testbench/dut/Required[213], /testbench/dut/Required[212], /testbench/dut/Required[211], /testbench/dut/Required[210], /testbench/dut/Required[209], /testbench/dut/Required[208], /testbench/dut/Required[207], /testbench/dut/Required[206], /testbench/dut/Required[205], /testbench/dut/Required[204], /testbench/dut/Required[203], /testbench/dut/Required[202], /testbench/dut/Required[201], /testbench/dut/Required[200], /testbench/dut/Required[199], /testbench/dut/Required[198], /testbench/dut/Required[197], /testbench/dut/Required[196], /testbench/dut/Required[195], /testbench/dut/Required[194], /testbench/dut/Required[193], /testbench/dut/Required[192], /testbench/dut/Required[191], /testbench/dut/Required[190], /testbench/dut/Required[189], /testbench/dut/Required[188], /testbench/dut/Required[187], /testbench/dut/Required[186], /testbench/dut/Required[185], /testbench/dut/Required[184], /testbench/dut/Required[183], /testbench/dut/Required[182], /testbench/dut/Required[181], /testbench/dut/Required[180], /testbench/dut/Required[179], /testbench/dut/Required[178], /testbench/dut/Required[177], /testbench/dut/Required[176], /testbench/dut/Required[175], /testbench/dut/Required[174], /testbench/dut/Required[173], /testbench/dut/Required[172], /testbench/dut/Required[171], /testbench/dut/Required[170], /testbench/dut/Required[169], /testbench/dut/Required[168], /testbench/dut/Required[167], /testbench/dut/Required[166], /testbench/dut/Required[165], /testbench/dut/Required[164], /testbench/dut/Required[163], /testbench/dut/Required[162], /testbench/dut/Required[161], /testbench/dut/Required[160] }} Minstret -quietly virtual signal -install /testbench/dut {/testbench/dut/Required[224] } TrapW -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Required[226], /testbench/dut/Required[225] }} PrivilegeModeW -quietly virtual signal -install /testbench/dut {/testbench/dut/Registers[0] } GPRWen -quietly virtual signal -install /testbench/dut {/testbench/dut/Registers[1] } FPRWen -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[6], /testbench/dut/Registers[5], /testbench/dut/Registers[4], /testbench/dut/Registers[3], /testbench/dut/Registers[2] }} GPRAdr -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[71], /testbench/dut/Registers[70], /testbench/dut/Registers[69], /testbench/dut/Registers[68], /testbench/dut/Registers[67], /testbench/dut/Registers[66], /testbench/dut/Registers[65], /testbench/dut/Registers[64], /testbench/dut/Registers[63], /testbench/dut/Registers[62], /testbench/dut/Registers[61], /testbench/dut/Registers[60], /testbench/dut/Registers[59], /testbench/dut/Registers[58], /testbench/dut/Registers[57], /testbench/dut/Registers[56], /testbench/dut/Registers[55], /testbench/dut/Registers[54], /testbench/dut/Registers[53], /testbench/dut/Registers[52], /testbench/dut/Registers[51], /testbench/dut/Registers[50], /testbench/dut/Registers[49], /testbench/dut/Registers[48], /testbench/dut/Registers[47], /testbench/dut/Registers[46], /testbench/dut/Registers[45], /testbench/dut/Registers[44], /testbench/dut/Registers[43], /testbench/dut/Registers[42], /testbench/dut/Registers[41], /testbench/dut/Registers[40], /testbench/dut/Registers[39], /testbench/dut/Registers[38], /testbench/dut/Registers[37], /testbench/dut/Registers[36], /testbench/dut/Registers[35], /testbench/dut/Registers[34], /testbench/dut/Registers[33], /testbench/dut/Registers[32], /testbench/dut/Registers[31], /testbench/dut/Registers[30], /testbench/dut/Registers[29], /testbench/dut/Registers[28], /testbench/dut/Registers[27], /testbench/dut/Registers[26], /testbench/dut/Registers[25], /testbench/dut/Registers[24], /testbench/dut/Registers[23], /testbench/dut/Registers[22], /testbench/dut/Registers[21], /testbench/dut/Registers[20], /testbench/dut/Registers[19], /testbench/dut/Registers[18], /testbench/dut/Registers[17], /testbench/dut/Registers[16], /testbench/dut/Registers[15], /testbench/dut/Registers[14], /testbench/dut/Registers[13], /testbench/dut/Registers[12], /testbench/dut/Registers[11], /testbench/dut/Registers[10], /testbench/dut/Registers[9], /testbench/dut/Registers[8], /testbench/dut/Registers[7] }} GPRValue -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[76], /testbench/dut/Registers[75], /testbench/dut/Registers[74], /testbench/dut/Registers[73], /testbench/dut/Registers[72], /testbench/dut/Registers[71] }} GPRAdr001 -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[139], /testbench/dut/Registers[138], /testbench/dut/Registers[137], /testbench/dut/Registers[136], /testbench/dut/Registers[135], /testbench/dut/Registers[134], /testbench/dut/Registers[133], /testbench/dut/Registers[132], /testbench/dut/Registers[131], /testbench/dut/Registers[130], /testbench/dut/Registers[129], /testbench/dut/Registers[128], /testbench/dut/Registers[127], /testbench/dut/Registers[126], /testbench/dut/Registers[125], /testbench/dut/Registers[124], /testbench/dut/Registers[123], /testbench/dut/Registers[122], /testbench/dut/Registers[121], /testbench/dut/Registers[120], /testbench/dut/Registers[119], /testbench/dut/Registers[118], /testbench/dut/Registers[117], /testbench/dut/Registers[116], /testbench/dut/Registers[115], /testbench/dut/Registers[114], /testbench/dut/Registers[113], /testbench/dut/Registers[112], /testbench/dut/Registers[111], /testbench/dut/Registers[110], /testbench/dut/Registers[109], /testbench/dut/Registers[108], /testbench/dut/Registers[107], /testbench/dut/Registers[106], /testbench/dut/Registers[105], /testbench/dut/Registers[104], /testbench/dut/Registers[103], /testbench/dut/Registers[102], /testbench/dut/Registers[101], /testbench/dut/Registers[100], /testbench/dut/Registers[99], /testbench/dut/Registers[98], /testbench/dut/Registers[97], /testbench/dut/Registers[96], /testbench/dut/Registers[95], /testbench/dut/Registers[94], /testbench/dut/Registers[93], /testbench/dut/Registers[92], /testbench/dut/Registers[91], /testbench/dut/Registers[90], /testbench/dut/Registers[89], /testbench/dut/Registers[88], /testbench/dut/Registers[87], /testbench/dut/Registers[86], /testbench/dut/Registers[85], /testbench/dut/Registers[84], /testbench/dut/Registers[83], /testbench/dut/Registers[82], /testbench/dut/Registers[81], /testbench/dut/Registers[80], /testbench/dut/Registers[79], /testbench/dut/Registers[78], /testbench/dut/Registers[77], /testbench/dut/Registers[76] }} FPRValue -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[70], /testbench/dut/Registers[69], /testbench/dut/Registers[68], /testbench/dut/Registers[67], /testbench/dut/Registers[66], /testbench/dut/Registers[65], /testbench/dut/Registers[64], /testbench/dut/Registers[63], /testbench/dut/Registers[62], /testbench/dut/Registers[61], /testbench/dut/Registers[60], /testbench/dut/Registers[59], /testbench/dut/Registers[58], /testbench/dut/Registers[57], /testbench/dut/Registers[56], /testbench/dut/Registers[55], /testbench/dut/Registers[54], /testbench/dut/Registers[53], /testbench/dut/Registers[52], /testbench/dut/Registers[51], /testbench/dut/Registers[50], /testbench/dut/Registers[49], /testbench/dut/Registers[48], /testbench/dut/Registers[47], /testbench/dut/Registers[46], /testbench/dut/Registers[45], /testbench/dut/Registers[44], /testbench/dut/Registers[43], /testbench/dut/Registers[42], /testbench/dut/Registers[41], /testbench/dut/Registers[40], /testbench/dut/Registers[39], /testbench/dut/Registers[38], /testbench/dut/Registers[37], /testbench/dut/Registers[36], /testbench/dut/Registers[35], /testbench/dut/Registers[34], /testbench/dut/Registers[33], /testbench/dut/Registers[32], /testbench/dut/Registers[31], /testbench/dut/Registers[30], /testbench/dut/Registers[29], /testbench/dut/Registers[28], /testbench/dut/Registers[27], /testbench/dut/Registers[26], /testbench/dut/Registers[25], /testbench/dut/Registers[24], /testbench/dut/Registers[23], /testbench/dut/Registers[22], /testbench/dut/Registers[21], /testbench/dut/Registers[20], /testbench/dut/Registers[19], /testbench/dut/Registers[18], /testbench/dut/Registers[17], /testbench/dut/Registers[16], /testbench/dut/Registers[15], /testbench/dut/Registers[14], /testbench/dut/Registers[13], /testbench/dut/Registers[12], /testbench/dut/Registers[11], /testbench/dut/Registers[10], /testbench/dut/Registers[9], /testbench/dut/Registers[8], /testbench/dut/Registers[7] }} GPRValue001 -quietly virtual function -install /testbench/dut -env /testbench/genblk3/#ALWAYS#441,293,397 { &{/testbench/dut/Registers[75], /testbench/dut/Registers[74], /testbench/dut/Registers[73], /testbench/dut/Registers[72], /testbench/dut/Registers[71] }} FPRAdr quietly WaveActivateNextPane {} 0 add wave -noupdate /testbench/clk add wave -noupdate /testbench/reset @@ -680,31 +660,25 @@ add wave -noupdate -group wfi /testbench/dut/core/priv/priv/pmd/WFITimeoutM add wave -noupdate -expand -group testbench /testbench/DCacheFlushStart add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFaultDelay -add wave -noupdate /testbench/dut/GPRWen -add wave -noupdate /testbench/dut/FPRWen -add wave -noupdate /testbench/dut/GPRAdr -add wave -noupdate /testbench/dut/FPRValue -add wave -noupdate /testbench/dut/GPRValue001 -add wave -noupdate /testbench/dut/FPRAdr -add wave -noupdate /testbench/dut/Registers -add wave -noupdate /testbench/dut/PCW -add wave -noupdate /testbench/dut/InstrW -add wave -noupdate /testbench/dut/Mcycle -add wave -noupdate /testbench/dut/Minstret -add wave -noupdate /testbench/dut/TrapW -add wave -noupdate /testbench/dut/PrivilegeModeW -add wave -noupdate /testbench/dut/Required -add wave -noupdate /testbench/dut/rvvisynth/NumCSRs -add wave -noupdate /testbench/dut/rvvisynth/CSRAdr0 -add wave -noupdate /testbench/dut/rvvisynth/CSRData0 -add wave -noupdate /testbench/dut/rvvisynth/CSRData1 -add wave -noupdate /testbench/dut/rvvisynth/CSRAdr2 -add wave -noupdate /testbench/dut/rvvisynth/CSRData2 add wave -noupdate /testbench/dut/rvvisynth/CSRs -add wave -noupdate /testbench/dut/rvvisynth/valid +add wave -noupdate -expand -group rvvi /testbench/dut/rvvisynth/clk +add wave -noupdate -expand -group rvvi /testbench/dut/rvvisynth/rvvi +add wave -noupdate -expand -group rvvi /testbench/dut/rvvisynth/valid +add wave -noupdate -expand -group packetizer -color Gold /testbench/dut/packetizer/CurrState +add wave -noupdate -expand -group packetizer -radix unsigned /testbench/dut/packetizer/WordCount +add wave -noupdate -expand -group packetizer /testbench/dut/packetizer/RVVIStall +add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wdata +add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wlast +add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wstrb +add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wvalid +add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wready +add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_tx_clk +add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_txd +add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_tx_en +add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_tx_er TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 4} {6586 ns} 1} {{Cursor 4} {2112952 ns} 0} {{Cursor 3} {403021 ns} 1} -quietly wave cursor active 2 +WaveRestoreCursors {{Cursor 4} {650 ns} 1} {{Cursor 4} {2090 ns} 1} {{Cursor 3} {364 ns} 0} +quietly wave cursor active 3 configure wave -namecolwidth 250 configure wave -valuecolwidth 194 configure wave -justifyvalue left @@ -719,4 +693,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {2039338 ns} {2323972 ns} +WaveRestoreZoom {266 ns} {618 ns} diff --git a/src/wally/packetizer.sv b/src/rvvi/packetizer.sv similarity index 96% rename from src/wally/packetizer.sv rename to src/rvvi/packetizer.sv index 4dc68dcab..00f394ab5 100644 --- a/src/wally/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -116,7 +116,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, // *** BUG BytesInFrame will eventually depend on the length of the data stored into the ethernet frame // for now this will be exactly 608 bits (76 bytes, 19 words) assign BytesInFrame = 12'd76; - assign BurstDone = WordCount == BytesInFrame[11:2]; + assign BurstDone = WordCount == (BytesInFrame[11:2] - 1'b1); assign m_axi_awid = '0; assign m_axi_awaddr = '0; // *** bug update to be based on the correct address during each beat. @@ -133,15 +133,15 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrame = {rvvi, Length, Tag, DstMac, SrcMac}; // *** fix me later - assign SrcMac = '0; - assign DstMac = '0; + assign SrcMac = 48'h8F54_0000_1654; // made something up + assign DstMac = 48'h4502_1111_6843; assign Tag = '0; assign Length = BytesInFrame + 16'd6 + 16'd6 + 16'd4 + 16'd2; assign m_axi_wdata = TotalFrameWords[WordCount]; assign m_axi_wstrb = '1; assign m_axi_wlast = BurstDone; - assign m_axi_wvalid = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS); + assign m_axi_wvalid = (CurrState == STATE_TRANS); assign m_axi_bready = 1'b1; // *** probably wrong. diff --git a/src/wally/rvvisynth.sv b/src/rvvi/rvvisynth.sv similarity index 100% rename from src/wally/rvvisynth.sv rename to src/rvvi/rvvisynth.sv diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index aaf52f550..bb9516435 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -135,8 +135,13 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic m_axi_rvalid; logic m_axi_rready; - - + logic [3:0] mii_txd; + logic mii_tx_en, mii_tx_er; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, @@ -145,8 +150,31 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .m_axi_arburst, .m_axi_arcache, .m_axi_arvalid, .m_axi_arready, .m_axi_rid, .m_axi_rdata, .m_axi_rresp, .m_axi_rlast, .m_axi_rvalid, .m_axi_rready); + eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), + .tx_axis_tdata(m_axi_wdata), .tx_axis_tkeep(m_axi_wstrb), .tx_axis_tvalid(m_axi_wvalid), .tx_axis_tready(m_axi_wready), + .tx_axis_tlast(m_axi_wlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), + .rx_axis_tlast(), .rx_axis_tuser(), + + // *** update these + .mii_rx_clk(clk), // *** need to be the mii clock + .mii_rxd('0), + .mii_rx_dv('0), + .mii_rx_er('0), + .mii_tx_clk(clk), // *** needs to be the mii clock + .mii_txd, + .mii_tx_en, + .mii_tx_er, + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) + ); + + + // *** finally fake the axi4 interface assign m_axi_awready = '1; - assign m_axi_wready = '1; + //assign m_axi_wready = '1; endmodule From d341974c5bb3cda8fe7d4f1869b0f50280c97323 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 15:52:13 -0500 Subject: [PATCH 011/163] Have rvvi to ethernet working. Now it is time to move the hardware to the FPGA. Ideally I don't want Wally to actually have any of this code since it's entirely debug code so it will move to the fpga/src directory. Then we'll need to add additional logic to the mmcm to generate the correct clocks. Finally we'll update the I/O to add ethernet. --- src/rvvi/packetizer.sv | 6 +++++- src/wally/wallypipelinedsoc.sv | 10 ++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 00f394ab5..3cf465268 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -85,6 +85,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic [15:0] Length; logic [TotalFrameLengthBits-1:0] TotalFrame; logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; + + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvviDelay; typedef enum {STATE_RDY, STATE_WAIT, STATE_TRANS, STATE_TRANS_DONE} statetype; statetype CurrState, NextState; @@ -111,6 +113,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign WordCountEnable = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS & TransReady); assign WordCountReset = CurrState == STATE_RDY; + flopenr #(187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)) rvvireg(m_axi_aclk, ~m_axi_aresetn, valid, rvvi, rvviDelay); + counter #(10) WordCounter(m_axi_aclk, WordCountReset, WordCountEnable, WordCount); // *** BUG BytesInFrame will eventually depend on the length of the data stored into the ethernet frame @@ -130,7 +134,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; end - assign TotalFrame = {rvvi, Length, Tag, DstMac, SrcMac}; + assign TotalFrame = {rvviDelay, Length, Tag, DstMac, SrcMac}; // *** fix me later assign SrcMac = 48'h8F54_0000_1654; // made something up diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index bb9516435..75265ab29 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -99,6 +99,10 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); + // a bunch of these signals would be needed for the xilinx ethernet IP + // but I switched to using https://github.com/alexforencich/verilog-ethernet + // so most arn't needed anymore. *** remove once I've confirmed this + // works in synthesis. logic [3:0] m_axi_awid; logic [12:0] m_axi_awaddr; logic [7:0] m_axi_awlen; @@ -140,8 +144,6 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; - - packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, @@ -171,10 +173,6 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) ); - - - // *** finally fake the axi4 interface assign m_axi_awready = '1; - //assign m_axi_wready = '1; endmodule From 1f7d732dca3d56f1d4943cb324d49259ef40903c Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 16:10:58 -0500 Subject: [PATCH 012/163] Moved the rvvisynth code to testbench since I only want this for simulation and fpga. --- sim/questa/wave.do | 38 ++++++------- src/rvvi/rvvisynth.sv | 100 ++++++++++++++++----------------- src/wally/wallypipelinedsoc.sv | 88 +---------------------------- testbench/testbench.sv | 92 +++++++++++++++++++++++++++++- testbench/wallywrapper.sv | 5 +- 5 files changed, 166 insertions(+), 157 deletions(-) diff --git a/sim/questa/wave.do b/sim/questa/wave.do index a1ae5fe8f..ec8dd82b3 100644 --- a/sim/questa/wave.do +++ b/sim/questa/wave.do @@ -660,25 +660,25 @@ add wave -noupdate -group wfi /testbench/dut/core/priv/priv/pmd/WFITimeoutM add wave -noupdate -expand -group testbench /testbench/DCacheFlushStart add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFault add wave -noupdate /testbench/dut/core/lsu/hptw/hptw/HPTWLoadPageFaultDelay -add wave -noupdate /testbench/dut/rvvisynth/CSRs -add wave -noupdate -expand -group rvvi /testbench/dut/rvvisynth/clk -add wave -noupdate -expand -group rvvi /testbench/dut/rvvisynth/rvvi -add wave -noupdate -expand -group rvvi /testbench/dut/rvvisynth/valid -add wave -noupdate -expand -group packetizer -color Gold /testbench/dut/packetizer/CurrState -add wave -noupdate -expand -group packetizer -radix unsigned /testbench/dut/packetizer/WordCount -add wave -noupdate -expand -group packetizer /testbench/dut/packetizer/RVVIStall -add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wdata -add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wlast -add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wstrb -add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wvalid -add wave -noupdate -expand -group packetizer -expand -group axi-write-interface /testbench/dut/packetizer/m_axi_wready -add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_tx_clk -add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_txd -add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_tx_en -add wave -noupdate -expand -group eth /testbench/dut/ethernet/mii_tx_er +add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/clk +add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/rvvi +add wave -noupdate -expand -group rvvi /testbench/rvvi_synth/rvvisynth/valid +add wave -noupdate -group packetizer -color Gold /testbench/rvvi_synth/packetizer/CurrState +add wave -noupdate -group packetizer -radix unsigned /testbench/rvvi_synth/packetizer/WordCount +add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/RVVIStall +add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/rvviDelay +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wdata +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wlast +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wstrb +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wvalid +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wready +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_clk +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_txd +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_en +add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_er TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 4} {650 ns} 1} {{Cursor 4} {2090 ns} 1} {{Cursor 3} {364 ns} 0} -quietly wave cursor active 3 +WaveRestoreCursors {{Cursor 4} {640 ns} 1} {{Cursor 4} {2400 ns} 1} {{Cursor 3} {554 ns} 0} {{Cursor 4} {120089 ns} 0} +quietly wave cursor active 4 configure wave -namecolwidth 250 configure wave -valuecolwidth 194 configure wave -justifyvalue left @@ -693,4 +693,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {266 ns} {618 ns} +WaveRestoreZoom {0 ns} {1033211 ns} diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index e5801cf09..27a1fe6d3 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -62,64 +62,64 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. - assign StallE = core.StallE; - assign StallM = core.StallM; - assign StallW = core.StallW; - assign FlushE = core.FlushE; - assign FlushM = core.FlushM; - assign FlushW = core.FlushW; - assign InstrValidM = core.ieu.InstrValidM; - assign InstrRawD = core.ifu.InstrRawD; - assign PCM = core.ifu.PCM; - assign Mcycle = core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = core.TrapM; - assign PrivilegeModeW = core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = core.ieu.dp.regf.a3; - assign GPRWen = core.ieu.dp.regf.we3; - assign GPRValue = core.ieu.dp.regf.wd3; - assign FPRAddr = core.fpu.fpu.fregfile.a4; - assign FPRWen = core.fpu.fpu.fregfile.we4; - assign FPRValue = core.fpu.fpu.fregfile.wd4; + assign StallE = dut.core.StallE; + assign StallM = dut.core.StallM; + assign StallW = dut.core.StallW; + assign FlushE = dut.core.FlushE; + assign FlushM = dut.core.FlushM; + assign FlushW = dut.core.FlushW; + assign InstrValidM = dut.core.ieu.InstrValidM; + assign InstrRawD = dut.core.ifu.InstrRawD; + assign PCM = dut.core.ifu.PCM; + assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = dut.core.TrapM; + assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = dut.core.ieu.dp.regf.a3; + assign GPRWen = dut.core.ieu.dp.regf.we3; + assign GPRValue = dut.core.ieu.dp.regf.wd3; + assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; - assign CSRArray[0] = core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 assign CSRArray[16] = 0; // 12'hF11 assign CSRArray[17] = 0; // 12'hF12 assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 assign CSRArray[19] = 0; // 12'hF15 assign CSRArray[20] = 0; // 12'h34A // supervisor CSRs - assign CSRArray[21] = core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D // user CSRs - assign CSRArray[33] = core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {core.priv.priv.csr.csru.csru.FRM_REGW, core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 // assign XLENZeros = '0; diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 75265ab29..236a653fb 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -32,10 +32,12 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( input logic reset_ext, // external asynchronous reset pin output logic reset, // reset synchronized to clk to prevent races on release // AHB Interface - input logic [P.AHBW-1:0] HRDATAEXT, + input logic [P.AHBW-1:0] HRDATAEXT, input logic HREADYEXT, HRESPEXT, output logic HSELEXT, output logic HSELEXTSDC, + // fpga debug signals + input logic RVVIStall, // outputs to external memory, shared with uncore memory output logic HCLK, HRESETn, output logic [P.PA_BITS-1:0] HADDR, @@ -68,11 +70,6 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic [63:0] MTIME_CLINT; // from CLINT to CSRs logic MExtInt,SExtInt; // from PLIC - localparam MAX_CSRS = 3; - logic valid; - logic RVVIStall; - logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; - // synchronize reset to SOC clock domain synchronizer resetsync(.clk, .d(reset_ext), .q(reset)); @@ -95,84 +92,5 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; end - - - rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); - - // a bunch of these signals would be needed for the xilinx ethernet IP - // but I switched to using https://github.com/alexforencich/verilog-ethernet - // so most arn't needed anymore. *** remove once I've confirmed this - // works in synthesis. - logic [3:0] m_axi_awid; - logic [12:0] m_axi_awaddr; - logic [7:0] m_axi_awlen; - logic [2:0] m_axi_awsize; - logic [1:0] m_axi_awburst; - logic [3:0] m_axi_awcache; - logic m_axi_awvalid; - logic m_axi_awready; - // axi 4 write data channel - logic [31:0] m_axi_wdata; - logic [3:0] m_axi_wstrb; - logic m_axi_wlast; - logic m_axi_wvalid; - logic m_axi_wready; - // axi 4 write response channel - logic [3:0] m_axi_bid; - logic [1:0] m_axi_bresp; - logic m_axi_bvalid; - logic m_axi_bready; - // axi 4 read address channel - logic [3:0] m_axi_arid; - logic [12:0] m_axi_araddr; - logic [7:0] m_axi_arlen; - logic [2:0] m_axi_arsize; - logic [1:0] m_axi_arburst; - logic [3:0] m_axi_arcache; - logic m_axi_arvalid; - logic m_axi_arready; - // axi 4 read data channel - logic [3:0] m_axi_rid; - logic [31:0] m_axi_rdata; - logic [1:0] m_axi_rresp; - logic m_axi_rlast; - logic m_axi_rvalid; - logic m_axi_rready; - - logic [3:0] mii_txd; - logic mii_tx_en, mii_tx_er; - - logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; - logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; - - packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, - .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, - .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready, .m_axi_bid, - .m_axi_bresp, .m_axi_bvalid, .m_axi_bready, .m_axi_arid, .m_axi_araddr, .m_axi_arlen, .m_axi_arsize, - .m_axi_arburst, .m_axi_arcache, .m_axi_arvalid, .m_axi_arready, .m_axi_rid, .m_axi_rdata, .m_axi_rresp, - .m_axi_rlast, .m_axi_rvalid, .m_axi_rready); - - eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), - .tx_axis_tdata(m_axi_wdata), .tx_axis_tkeep(m_axi_wstrb), .tx_axis_tvalid(m_axi_wvalid), .tx_axis_tready(m_axi_wready), - .tx_axis_tlast(m_axi_wlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), - .rx_axis_tlast(), .rx_axis_tuser(), - - // *** update these - .mii_rx_clk(clk), // *** need to be the mii clock - .mii_rxd('0), - .mii_rx_dv('0), - .mii_rx_er('0), - .mii_tx_clk(clk), // *** needs to be the mii clock - .mii_txd, - .mii_tx_en, - .mii_tx_er, - - // status - .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, - .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, - .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) - ); - - assign m_axi_awready = '1; endmodule diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 71aaa8126..ed511da68 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -33,6 +33,8 @@ `include "idv/idv.svh" `endif +// *** bug replace with config? +`define RVVI_SYNTH_SUPPORTED 1 import cvw::*; @@ -110,6 +112,7 @@ module testbench; logic Validate; logic SelectTest; logic TestComplete; + logic RVVIStall; initial begin // look for arguments passed to simulation, or use defaults @@ -577,7 +580,7 @@ module testbench; assign SDCIntr = 1'b0; end - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .RVVIStall, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS); @@ -587,6 +590,93 @@ module testbench; clk = 1'b1; # 5; clk = 1'b0; # 5; end + if(`RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + localparam MAX_CSRS = 3; + logic valid; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); + + // a bunch of these signals would be needed for the xilinx ethernet IP + // but I switched to using https://github.com/alexforencich/verilog-ethernet + // so most arn't needed anymore. *** remove once I've confirmed this + // works in synthesis. + logic [3:0] m_axi_awid; + logic [12:0] m_axi_awaddr; + logic [7:0] m_axi_awlen; + logic [2:0] m_axi_awsize; + logic [1:0] m_axi_awburst; + logic [3:0] m_axi_awcache; + logic m_axi_awvalid; + logic m_axi_awready; + // axi 4 write data channel + logic [31:0] m_axi_wdata; + logic [3:0] m_axi_wstrb; + logic m_axi_wlast; + logic m_axi_wvalid; + logic m_axi_wready; + // axi 4 write response channel + logic [3:0] m_axi_bid; + logic [1:0] m_axi_bresp; + logic m_axi_bvalid; + logic m_axi_bready; + // axi 4 read address channel + logic [3:0] m_axi_arid; + logic [12:0] m_axi_araddr; + logic [7:0] m_axi_arlen; + logic [2:0] m_axi_arsize; + logic [1:0] m_axi_arburst; + logic [3:0] m_axi_arcache; + logic m_axi_arvalid; + logic m_axi_arready; + // axi 4 read data channel + logic [3:0] m_axi_rid; + logic [31:0] m_axi_rdata; + logic [1:0] m_axi_rresp; + logic m_axi_rlast; + logic m_axi_rvalid; + logic m_axi_rready; + + logic [3:0] mii_txd; + logic mii_tx_en, mii_tx_er; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, + .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, + .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready, .m_axi_bid, + .m_axi_bresp, .m_axi_bvalid, .m_axi_bready, .m_axi_arid, .m_axi_araddr, .m_axi_arlen, .m_axi_arsize, + .m_axi_arburst, .m_axi_arcache, .m_axi_arvalid, .m_axi_arready, .m_axi_rid, .m_axi_rdata, .m_axi_rresp, + .m_axi_rlast, .m_axi_rvalid, .m_axi_rready); + + eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), + .tx_axis_tdata(m_axi_wdata), .tx_axis_tkeep(m_axi_wstrb), .tx_axis_tvalid(m_axi_wvalid), .tx_axis_tready(m_axi_wready), + .tx_axis_tlast(m_axi_wlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), + .rx_axis_tlast(), .rx_axis_tuser(), + + // *** update these + .mii_rx_clk(clk), // *** need to be the mii clock + .mii_rxd('0), + .mii_rx_dv('0), + .mii_rx_er('0), + .mii_tx_clk(clk), // *** needs to be the mii clock + .mii_txd, + .mii_tx_en, + .mii_tx_er, + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) + ); + + assign m_axi_awready = '1; + end else begin + assign RVVIStall = '0; + end + + /* // Print key info each cycle for debugging always @(posedge clk) begin diff --git a/testbench/wallywrapper.sv b/testbench/wallywrapper.sv index 990ebfe74..234a11fdf 100644 --- a/testbench/wallywrapper.sv +++ b/testbench/wallywrapper.sv @@ -57,7 +57,7 @@ module wallywrapper; logic HREADY; logic HSELEXT; logic HSELEXTSDC; - + logic RVVIStall; // instantiate device to be tested assign GPIOIN = 0; @@ -67,8 +67,9 @@ module wallywrapper; assign HRESPEXT = 0; assign HRDATAEXT = 0; + assign RVVIStall = '0; - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .RVVIStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr); From 263be861191456bc0e6db474276005ab52c480ce Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 16:27:09 -0500 Subject: [PATCH 013/163] Packetizer cleanup. --- src/rvvi/packetizer.sv | 14 -------------- testbench/testbench.sv | 8 -------- 2 files changed, 22 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 3cf465268..8067ba412 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -34,13 +34,6 @@ module packetizer import cvw::*; #(parameter cvw_t P, input logic m_axi_aclk, m_axi_aresetn, output logic RVVIStall, // axi 4 write address channel - output logic [3:0] m_axi_awid, - output logic [12:0] m_axi_awaddr, - output logic [7:0] m_axi_awlen, - output logic [2:0] m_axi_awsize, - output logic [1:0] m_axi_awburst, - output logic [3:0] m_axi_awcache, - output logic m_axi_awvalid, input logic m_axi_awready, // axi 4 write data channel output logic [31:0] m_axi_wdata, @@ -122,13 +115,6 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign BytesInFrame = 12'd76; assign BurstDone = WordCount == (BytesInFrame[11:2] - 1'b1); - assign m_axi_awid = '0; - assign m_axi_awaddr = '0; // *** bug update to be based on the correct address during each beat. - assign m_axi_awlen = BytesInFrame[11:2]; - assign m_axi_awsize = 3'b010; // 4 bytes - assign m_axi_awburst = 2'b01; // increment - assign m_axi_awcache = '0; - assign m_axi_awvalid = (CurrState == STATE_RDY & valid) | CurrState == STATE_TRANS; genvar index; for (index = 0; index < TotalFrameLengthBytes/4; index++) begin assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; diff --git a/testbench/testbench.sv b/testbench/testbench.sv index ed511da68..2bcabbfa4 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -601,13 +601,6 @@ module testbench; // but I switched to using https://github.com/alexforencich/verilog-ethernet // so most arn't needed anymore. *** remove once I've confirmed this // works in synthesis. - logic [3:0] m_axi_awid; - logic [12:0] m_axi_awaddr; - logic [7:0] m_axi_awlen; - logic [2:0] m_axi_awsize; - logic [1:0] m_axi_awburst; - logic [3:0] m_axi_awcache; - logic m_axi_awvalid; logic m_axi_awready; // axi 4 write data channel logic [31:0] m_axi_wdata; @@ -644,7 +637,6 @@ module testbench; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, - .m_axi_awid, .m_axi_awaddr, .m_axi_awlen, .m_axi_awsize, .m_axi_awburst, .m_axi_awcache, .m_axi_awvalid, .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready, .m_axi_bid, .m_axi_bresp, .m_axi_bvalid, .m_axi_bready, .m_axi_arid, .m_axi_araddr, .m_axi_arlen, .m_axi_arsize, .m_axi_arburst, .m_axi_arcache, .m_axi_arvalid, .m_axi_arready, .m_axi_rid, .m_axi_rdata, .m_axi_rresp, From bd2ec879d2e1f40a573d2469a644f66d1db5f621 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 16:31:27 -0500 Subject: [PATCH 014/163] Removed unused axi signals from packetizer. --- src/rvvi/packetizer.sv | 28 +--------------------------- testbench/testbench.sv | 30 +----------------------------- 2 files changed, 2 insertions(+), 56 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 8067ba412..49828ab38 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -40,28 +40,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, output logic [3:0] m_axi_wstrb, output logic m_axi_wlast, output logic m_axi_wvalid, - input logic m_axi_wready, - // axi 4 write response channel - input logic [3:0] m_axi_bid, - input logic [1:0] m_axi_bresp, - input logic m_axi_bvalid, - output logic m_axi_bready, - // axi 4 read address channel - output logic [3:0] m_axi_arid, - output logic [12:0] m_axi_araddr, - output logic [7:0] m_axi_arlen, - output logic [2:0] m_axi_arsize, - output logic [1:0] m_axi_arburst, - output logic [3:0] m_axi_arcache, - output logic m_axi_arvalid, - input logic m_axi_arready, - // axi 4 read data channel - input logic [3:0] m_axi_rid, - input logic [31:0] m_axi_rdata, - input logic [1:0] m_axi_rresp, - input logic m_axi_rlast, - input logic m_axi_rvalid, - output logic m_axi_rready + input logic m_axi_wready ); localparam TotalFrameLengthBits = 2*48+32+16+187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12); @@ -133,10 +112,5 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign m_axi_wlast = BurstDone; assign m_axi_wvalid = (CurrState == STATE_TRANS); - assign m_axi_bready = 1'b1; // *** probably wrong. - - // we aren't using the read channels. This ethernet device isn't going to read anything for now - assign {m_axi_arid, m_axi_araddr, m_axi_arlen, m_axi_arsize, m_axi_arburst, m_axi_arcache, m_axi_arvalid, m_axi_rready} = '0; - endmodule diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 2bcabbfa4..5bc47b1ba 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -597,10 +597,6 @@ module testbench; rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); - // a bunch of these signals would be needed for the xilinx ethernet IP - // but I switched to using https://github.com/alexforencich/verilog-ethernet - // so most arn't needed anymore. *** remove once I've confirmed this - // works in synthesis. logic m_axi_awready; // axi 4 write data channel logic [31:0] m_axi_wdata; @@ -608,27 +604,6 @@ module testbench; logic m_axi_wlast; logic m_axi_wvalid; logic m_axi_wready; - // axi 4 write response channel - logic [3:0] m_axi_bid; - logic [1:0] m_axi_bresp; - logic m_axi_bvalid; - logic m_axi_bready; - // axi 4 read address channel - logic [3:0] m_axi_arid; - logic [12:0] m_axi_araddr; - logic [7:0] m_axi_arlen; - logic [2:0] m_axi_arsize; - logic [1:0] m_axi_arburst; - logic [3:0] m_axi_arcache; - logic m_axi_arvalid; - logic m_axi_arready; - // axi 4 read data channel - logic [3:0] m_axi_rid; - logic [31:0] m_axi_rdata; - logic [1:0] m_axi_rresp; - logic m_axi_rlast; - logic m_axi_rvalid; - logic m_axi_rready; logic [3:0] mii_txd; logic mii_tx_en, mii_tx_er; @@ -637,10 +612,7 @@ module testbench; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, - .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready, .m_axi_bid, - .m_axi_bresp, .m_axi_bvalid, .m_axi_bready, .m_axi_arid, .m_axi_araddr, .m_axi_arlen, .m_axi_arsize, - .m_axi_arburst, .m_axi_arcache, .m_axi_arvalid, .m_axi_arready, .m_axi_rid, .m_axi_rdata, .m_axi_rresp, - .m_axi_rlast, .m_axi_rvalid, .m_axi_rready); + .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready); eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), .tx_axis_tdata(m_axi_wdata), .tx_axis_tkeep(m_axi_wstrb), .tx_axis_tvalid(m_axi_wvalid), .tx_axis_tready(m_axi_wready), From 73261e7f89ca3c2109c75dadc39d8647cc01ccd1 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 16:34:33 -0500 Subject: [PATCH 015/163] More cleanup. Close to the simpliest it can be. --- src/rvvi/packetizer.sv | 3 +-- testbench/testbench.sv | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 49828ab38..b5a2cb695 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -34,7 +34,6 @@ module packetizer import cvw::*; #(parameter cvw_t P, input logic m_axi_aclk, m_axi_aresetn, output logic RVVIStall, // axi 4 write address channel - input logic m_axi_awready, // axi 4 write data channel output logic [31:0] m_axi_wdata, output logic [3:0] m_axi_wstrb, @@ -81,7 +80,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, end assign RVVIStall = CurrState != STATE_RDY; - assign TransReady = m_axi_awready & m_axi_wready; + assign TransReady = m_axi_wready; assign WordCountEnable = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS & TransReady); assign WordCountReset = CurrState == STATE_RDY; diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 5bc47b1ba..3895a157a 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -597,7 +597,6 @@ module testbench; rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); - logic m_axi_awready; // axi 4 write data channel logic [31:0] m_axi_wdata; logic [3:0] m_axi_wstrb; @@ -612,7 +611,7 @@ module testbench; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, - .m_axi_awready, .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready); + .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready); eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), .tx_axis_tdata(m_axi_wdata), .tx_axis_tkeep(m_axi_wstrb), .tx_axis_tvalid(m_axi_wvalid), .tx_axis_tready(m_axi_wready), @@ -635,7 +634,6 @@ module testbench; .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) ); - assign m_axi_awready = '1; end else begin assign RVVIStall = '0; end From dc09e1c0c5f9ef0c64e458b7e2d36c9ebce76046 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 24 May 2024 16:38:47 -0500 Subject: [PATCH 016/163] Modified names so they don't conflict with FPGA's axi signals. --- sim/questa/wave.do | 10 +++++----- src/rvvi/packetizer.sv | 20 ++++++++++---------- testbench/testbench.sv | 16 ++++++++-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/sim/questa/wave.do b/sim/questa/wave.do index ec8dd82b3..8ce781d18 100644 --- a/sim/questa/wave.do +++ b/sim/questa/wave.do @@ -667,11 +667,11 @@ add wave -noupdate -group packetizer -color Gold /testbench/rvvi_synth/packetize add wave -noupdate -group packetizer -radix unsigned /testbench/rvvi_synth/packetizer/WordCount add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/RVVIStall add wave -noupdate -group packetizer /testbench/rvvi_synth/packetizer/rvviDelay -add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wdata -add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wlast -add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wstrb -add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wvalid -add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/m_axi_wready +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWdata +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWlast +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWstrb +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWvalid +add wave -noupdate -group packetizer -expand -group axi-write-interface /testbench/rvvi_synth/packetizer/RvviAxiWready add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_clk add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_txd add wave -noupdate -expand -group eth /testbench/rvvi_synth/ethernet/mii_tx_en diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index b5a2cb695..93390d03b 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -35,11 +35,11 @@ module packetizer import cvw::*; #(parameter cvw_t P, output logic RVVIStall, // axi 4 write address channel // axi 4 write data channel - output logic [31:0] m_axi_wdata, - output logic [3:0] m_axi_wstrb, - output logic m_axi_wlast, - output logic m_axi_wvalid, - input logic m_axi_wready + output logic [31:0] RvviAxiWdata, + output logic [3:0] RvviAxiWstrb, + output logic RvviAxiWlast, + output logic RvviAxiWvalid, + input logic RvviAxiWready ); localparam TotalFrameLengthBits = 2*48+32+16+187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12); @@ -80,7 +80,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, end assign RVVIStall = CurrState != STATE_RDY; - assign TransReady = m_axi_wready; + assign TransReady = RvviAxiWready; assign WordCountEnable = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS & TransReady); assign WordCountReset = CurrState == STATE_RDY; @@ -106,10 +106,10 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign Tag = '0; assign Length = BytesInFrame + 16'd6 + 16'd6 + 16'd4 + 16'd2; - assign m_axi_wdata = TotalFrameWords[WordCount]; - assign m_axi_wstrb = '1; - assign m_axi_wlast = BurstDone; - assign m_axi_wvalid = (CurrState == STATE_TRANS); + assign RvviAxiWdata = TotalFrameWords[WordCount]; + assign RvviAxiWstrb = '1; + assign RvviAxiWlast = BurstDone; + assign RvviAxiWvalid = (CurrState == STATE_TRANS); endmodule diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 3895a157a..6020088e6 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -598,11 +598,11 @@ module testbench; rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); // axi 4 write data channel - logic [31:0] m_axi_wdata; - logic [3:0] m_axi_wstrb; - logic m_axi_wlast; - logic m_axi_wvalid; - logic m_axi_wready; + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; logic [3:0] mii_txd; logic mii_tx_en, mii_tx_er; @@ -611,11 +611,11 @@ module testbench; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, - .m_axi_wdata, .m_axi_wstrb, .m_axi_wlast, .m_axi_wvalid, .m_axi_wready); + .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), - .tx_axis_tdata(m_axi_wdata), .tx_axis_tkeep(m_axi_wstrb), .tx_axis_tvalid(m_axi_wvalid), .tx_axis_tready(m_axi_wready), - .tx_axis_tlast(m_axi_wlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), + .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), .rx_axis_tlast(), .rx_axis_tuser(), // *** update these From 970305575803f13932c91ce069c71be644c3c3f5 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Thu, 30 May 2024 15:37:17 -0500 Subject: [PATCH 017/163] The FPGA is synthesizing with the rvvi and ethernet hardware. --- fpga/constraints/constraints-ArtyA7.xdc | 26 ++++++ fpga/generator/xlnx_mmcm.tcl | 3 +- fpga/src/fpgaTopArtyA7.sv | 62 ++++++++++++++- src/rvvi/rvvisynth.sv | 100 ++++++++++++------------ 4 files changed, 138 insertions(+), 53 deletions(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 6fc660e8d..556c75c43 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -9,6 +9,32 @@ set_property PACKAGE_PIN E3 [get_ports {default_100mhz_clk}] set_property IOSTANDARD LVCMOS33 [get_ports {default_100mhz_clk}] +##### RVVI Ethernet #### +# taken from https://github.com/alexforencich/verilog-ethernet/blob/master/example/Arty/fpga/fpga.xdc +set_property -dict {LOC F15 IOSTANDARD LVCMOS33} [get_ports phy_rx_clk] +set_property -dict {LOC D18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[0]}] +set_property -dict {LOC E17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[1]}] +set_property -dict {LOC E18 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[2]}] +set_property -dict {LOC G17 IOSTANDARD LVCMOS33} [get_ports {phy_rxd[3]}] +set_property -dict {LOC G16 IOSTANDARD LVCMOS33} [get_ports phy_rx_dv] +set_property -dict {LOC C17 IOSTANDARD LVCMOS33} [get_ports phy_rx_er] +set_property -dict {LOC H16 IOSTANDARD LVCMOS33} [get_ports phy_tx_clk] +set_property -dict {LOC H14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[0]}] +set_property -dict {LOC J14 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[1]}] +set_property -dict {LOC J13 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[2]}] +set_property -dict {LOC H17 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports {phy_txd[3]}] +set_property -dict {LOC H15 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports phy_tx_en] +set_property -dict {LOC D17 IOSTANDARD LVCMOS33} [get_ports phy_col] +set_property -dict {LOC G14 IOSTANDARD LVCMOS33} [get_ports phy_crs] +set_property -dict {LOC G18 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_ref_clk] +set_property -dict {LOC C16 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports phy_reset_n] + +create_clock -period 40.000 -name phy_rx_clk [get_ports phy_rx_clk] +create_clock -period 40.000 -name phy_tx_clk [get_ports phy_tx_clk] + +set_false_path -to [get_ports {phy_ref_clk phy_reset_n}] +set_output_delay 0 [get_ports {phy_ref_clk phy_reset_n}] + ##### GPI #### set_property PACKAGE_PIN A8 [get_ports {GPI[0]}] set_property PACKAGE_PIN C9 [get_ports {GPI[1]}] diff --git a/fpga/generator/xlnx_mmcm.tcl b/fpga/generator/xlnx_mmcm.tcl index 2f003e7a5..8335c397a 100644 --- a/fpga/generator/xlnx_mmcm.tcl +++ b/fpga/generator/xlnx_mmcm.tcl @@ -12,10 +12,11 @@ set_property -dict [list CONFIG.PRIM_IN_FREQ {100.000} \ CONFIG.NUM_OUT_CLKS {3} \ CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT3_USED {true} \ - CONFIG.CLKOUT4_USED {false} \ + CONFIG.CLKOUT4_USED {true} \ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {166.66667} \ CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20} \ + CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {25} \ CONFIG.CLKIN1_JITTER_PS {10.0} \ ] [get_ips $ipName] diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 20e8adb81..295c62c38 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -44,6 +44,21 @@ module fpgaTop inout SDCCmd, input SDCCD, + /* + * Ethernet: 100BASE-T MII + */ + output phy_ref_clk, + input phy_rx_clk, + input [3:0] phy_rxd, + input phy_rx_dv, + input phy_rx_er, + input phy_tx_clk, + output [3:0] phy_txd, + output phy_tx_en, + input phy_col, // nc + input phy_crs, // nc + output phy_reset_n, + inout [15:0] ddr3_dq, inout [1:0] ddr3_dqs_n, inout [1:0] ddr3_dqs_p, @@ -428,7 +443,8 @@ module fpgaTop wire mmcm_locked; wire [11:0] device_temp; wire mmcm1_locked; - + + logic RVVIStall; assign GPIOIN = {28'b0, GPI}; assign GPO = GPIOOUT[4:0]; @@ -446,6 +462,7 @@ module fpgaTop xlnx_mmcm xln_mmcm(.clk_out1(clk167), .clk_out2(clk200), .clk_out3(CPUCLK), + .clk_out4(phy_ref_clk), .reset(1'b0), .locked(mmcm1_locked), .clk_in1(default_100mhz_clk)); @@ -496,7 +513,7 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr); + .UARTSin, .UARTSout, .SDCIntr, .RVVIStall); // ahb lite to axi bridge @@ -1098,6 +1115,47 @@ module fpgaTop .init_calib_complete(c0_init_calib_complete), .device_temp(device_temp)); + localparam MAX_CSRS = 3; + logic valid; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .valid, .rvvi); + + // axi 4 write data channel + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, + .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); + + eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), + .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), + .rx_axis_tlast(), .rx_axis_tuser(), + + // *** update these + .mii_rx_clk(phy_rx_clk), + .mii_rxd(phy_rxd), + .mii_rx_dv(phy_rx_dv), + .mii_rx_er(phy_rx_er), + .mii_tx_clk(phy_tx_clk), + .mii_txd(phy_txd), + .mii_tx_en(phy_tx_en), + .mii_tx_er(), + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) + ); + + assign phy_reset_n = ~bus_struct_reset; endmodule diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index 27a1fe6d3..df96ba446 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -62,64 +62,64 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. - assign StallE = dut.core.StallE; - assign StallM = dut.core.StallM; - assign StallW = dut.core.StallW; - assign FlushE = dut.core.FlushE; - assign FlushM = dut.core.FlushM; - assign FlushW = dut.core.FlushW; - assign InstrValidM = dut.core.ieu.InstrValidM; - assign InstrRawD = dut.core.ifu.InstrRawD; - assign PCM = dut.core.ifu.PCM; - assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = dut.core.TrapM; - assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = dut.core.ieu.dp.regf.a3; - assign GPRWen = dut.core.ieu.dp.regf.we3; - assign GPRValue = dut.core.ieu.dp.regf.wd3; - assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; - assign FPRWen = dut.core.fpu.fpu.fregfile.we4; - assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; + assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; + assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; + assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; + assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; + assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; + assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; + assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; + assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; + assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; + assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; + assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; + assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; + assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; + assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; + assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; + assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; - assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 assign CSRArray[16] = 0; // 12'hF11 assign CSRArray[17] = 0; // 12'hF12 assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 assign CSRArray[19] = 0; // 12'hF15 assign CSRArray[20] = 0; // 12'h34A // supervisor CSRs - assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D // user CSRs - assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 // assign XLENZeros = '0; From 38ddbf860e610ba20cd78df8d5b35fb2d0d3e92b Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Thu, 30 May 2024 16:19:28 -0500 Subject: [PATCH 018/163] Fixed bug with mmcm not generating the 4th clock. --- fpga/generator/xlnx_mmcm.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/generator/xlnx_mmcm.tcl b/fpga/generator/xlnx_mmcm.tcl index 8335c397a..146a9cf41 100644 --- a/fpga/generator/xlnx_mmcm.tcl +++ b/fpga/generator/xlnx_mmcm.tcl @@ -16,7 +16,7 @@ set_property -dict [list CONFIG.PRIM_IN_FREQ {100.000} \ CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {166.66667} \ CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20} \ - CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {25} \ + CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {25} \ CONFIG.CLKIN1_JITTER_PS {10.0} \ ] [get_ips $ipName] From ca90c6ba48a8c60f6d8ca99606345872f5111012 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Thu, 30 May 2024 16:33:49 -0500 Subject: [PATCH 019/163] Added the ethernet files. These are part of another repo. We should remove before mainlining this. --- src/rvvi/axis_adapter.sv | 324 ++++++++++ src/rvvi/axis_async_fifo.sv | 909 ++++++++++++++++++++++++++++ src/rvvi/axis_async_fifo_adapter.sv | 377 ++++++++++++ src/rvvi/axis_gmii_rx.sv | 357 +++++++++++ src/rvvi/axis_gmii_tx.sv | 457 ++++++++++++++ src/rvvi/eth_axis_tx.sv | 408 +++++++++++++ src/rvvi/eth_mac_1g.sv | 643 ++++++++++++++++++++ src/rvvi/eth_mac_mii.sv | 175 ++++++ src/rvvi/eth_mac_mii_fifo.sv | 339 +++++++++++ src/rvvi/lfsr.sv | 446 ++++++++++++++ src/rvvi/mac_ctrl_rx.sv | 447 ++++++++++++++ src/rvvi/mac_ctrl_tx.sv | 420 +++++++++++++ src/rvvi/mac_pause_ctrl_rx.sv | 220 +++++++ src/rvvi/mac_pause_ctrl_tx.sv | 312 ++++++++++ src/rvvi/mii_phy_if.sv | 140 +++++ src/rvvi/ssio_ddr_in.sv | 150 +++++ src/rvvi/ssio_sdr_in.sv | 166 +++++ 17 files changed, 6290 insertions(+) create mode 100644 src/rvvi/axis_adapter.sv create mode 100644 src/rvvi/axis_async_fifo.sv create mode 100644 src/rvvi/axis_async_fifo_adapter.sv create mode 100644 src/rvvi/axis_gmii_rx.sv create mode 100644 src/rvvi/axis_gmii_tx.sv create mode 100644 src/rvvi/eth_axis_tx.sv create mode 100644 src/rvvi/eth_mac_1g.sv create mode 100644 src/rvvi/eth_mac_mii.sv create mode 100644 src/rvvi/eth_mac_mii_fifo.sv create mode 100644 src/rvvi/lfsr.sv create mode 100644 src/rvvi/mac_ctrl_rx.sv create mode 100644 src/rvvi/mac_ctrl_tx.sv create mode 100644 src/rvvi/mac_pause_ctrl_rx.sv create mode 100644 src/rvvi/mac_pause_ctrl_tx.sv create mode 100644 src/rvvi/mii_phy_if.sv create mode 100644 src/rvvi/ssio_ddr_in.sv create mode 100644 src/rvvi/ssio_sdr_in.sv diff --git a/src/rvvi/axis_adapter.sv b/src/rvvi/axis_adapter.sv new file mode 100644 index 000000000..8807a03b7 --- /dev/null +++ b/src/rvvi/axis_adapter.sv @@ -0,0 +1,324 @@ +/* + +Copyright (c) 2014-2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * AXI4-Stream bus width adapter + */ +module axis_adapter # +( + // Width of input AXI stream interface in bits + parameter S_DATA_WIDTH = 8, + // Propagate tkeep signal on input interface + // If disabled, tkeep assumed to be 1'b1 + parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8), + // tkeep signal width (words per cycle) on input interface + parameter S_KEEP_WIDTH = ((S_DATA_WIDTH+7)/8), + // Width of output AXI stream interface in bits + parameter M_DATA_WIDTH = 8, + // Propagate tkeep signal on output interface + // If disabled, tkeep assumed to be 1'b1 + parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8), + // tkeep signal width (words per cycle) on output interface + parameter M_KEEP_WIDTH = ((M_DATA_WIDTH+7)/8), + // Propagate tid signal + parameter ID_ENABLE = 0, + // tid signal width + parameter ID_WIDTH = 8, + // Propagate tdest signal + parameter DEST_ENABLE = 0, + // tdest signal width + parameter DEST_WIDTH = 8, + // Propagate tuser signal + parameter USER_ENABLE = 1, + // tuser signal width + parameter USER_WIDTH = 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [S_DATA_WIDTH-1:0] s_axis_tdata, + input wire [S_KEEP_WIDTH-1:0] s_axis_tkeep, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire [ID_WIDTH-1:0] s_axis_tid, + input wire [DEST_WIDTH-1:0] s_axis_tdest, + input wire [USER_WIDTH-1:0] s_axis_tuser, + + /* + * AXI output + */ + output wire [M_DATA_WIDTH-1:0] m_axis_tdata, + output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire [ID_WIDTH-1:0] m_axis_tid, + output wire [DEST_WIDTH-1:0] m_axis_tdest, + output wire [USER_WIDTH-1:0] m_axis_tuser +); + +// force keep width to 1 when disabled +localparam S_BYTE_LANES = S_KEEP_ENABLE ? S_KEEP_WIDTH : 1; +localparam M_BYTE_LANES = M_KEEP_ENABLE ? M_KEEP_WIDTH : 1; + +// bus byte sizes (must be identical) +localparam S_BYTE_SIZE = S_DATA_WIDTH / S_BYTE_LANES; +localparam M_BYTE_SIZE = M_DATA_WIDTH / M_BYTE_LANES; + +// bus width assertions +initial begin + if (S_BYTE_SIZE * S_BYTE_LANES != S_DATA_WIDTH) begin + $error("Error: input data width not evenly divisible (instance %m)"); + $finish; + end + + if (M_BYTE_SIZE * M_BYTE_LANES != M_DATA_WIDTH) begin + $error("Error: output data width not evenly divisible (instance %m)"); + $finish; + end + + if (S_BYTE_SIZE != M_BYTE_SIZE) begin + $error("Error: byte size mismatch (instance %m)"); + $finish; + end +end + +generate + +if (M_BYTE_LANES == S_BYTE_LANES) begin : bypass + // same width; bypass + + assign s_axis_tready = m_axis_tready; + + assign m_axis_tdata = s_axis_tdata; + assign m_axis_tkeep = M_KEEP_ENABLE ? s_axis_tkeep : {M_KEEP_WIDTH{1'b1}}; + assign m_axis_tvalid = s_axis_tvalid; + assign m_axis_tlast = s_axis_tlast; + assign m_axis_tid = ID_ENABLE ? s_axis_tid : {ID_WIDTH{1'b0}}; + assign m_axis_tdest = DEST_ENABLE ? s_axis_tdest : {DEST_WIDTH{1'b0}}; + assign m_axis_tuser = USER_ENABLE ? s_axis_tuser : {USER_WIDTH{1'b0}}; + +end else if (M_BYTE_LANES > S_BYTE_LANES) begin : upsize + // output is wider; upsize + + // required number of segments in wider bus + localparam SEG_COUNT = M_BYTE_LANES / S_BYTE_LANES; + // data width and keep width per segment + localparam SEG_DATA_WIDTH = M_DATA_WIDTH / SEG_COUNT; + localparam SEG_KEEP_WIDTH = M_BYTE_LANES / SEG_COUNT; + + reg [$clog2(SEG_COUNT)-1:0] seg_reg = 0; + + reg [S_DATA_WIDTH-1:0] s_axis_tdata_reg = {S_DATA_WIDTH{1'b0}}; + reg [S_KEEP_WIDTH-1:0] s_axis_tkeep_reg = {S_KEEP_WIDTH{1'b0}}; + reg s_axis_tvalid_reg = 1'b0; + reg s_axis_tlast_reg = 1'b0; + reg [ID_WIDTH-1:0] s_axis_tid_reg = {ID_WIDTH{1'b0}}; + reg [DEST_WIDTH-1:0] s_axis_tdest_reg = {DEST_WIDTH{1'b0}}; + reg [USER_WIDTH-1:0] s_axis_tuser_reg = {USER_WIDTH{1'b0}}; + + reg [M_DATA_WIDTH-1:0] m_axis_tdata_reg = {M_DATA_WIDTH{1'b0}}; + reg [M_KEEP_WIDTH-1:0] m_axis_tkeep_reg = {M_KEEP_WIDTH{1'b0}}; + reg m_axis_tvalid_reg = 1'b0; + reg m_axis_tlast_reg = 1'b0; + reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; + reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; + reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + + assign s_axis_tready = !s_axis_tvalid_reg; + + assign m_axis_tdata = m_axis_tdata_reg; + assign m_axis_tkeep = M_KEEP_ENABLE ? m_axis_tkeep_reg : {M_KEEP_WIDTH{1'b1}}; + assign m_axis_tvalid = m_axis_tvalid_reg; + assign m_axis_tlast = m_axis_tlast_reg; + assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; + assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; + assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; + + always @(posedge clk) begin + m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready; + + if (!m_axis_tvalid_reg || m_axis_tready) begin + // output register empty + + if (seg_reg == 0) begin + m_axis_tdata_reg[seg_reg*SEG_DATA_WIDTH +: SEG_DATA_WIDTH] <= s_axis_tvalid_reg ? s_axis_tdata_reg : s_axis_tdata; + m_axis_tkeep_reg <= s_axis_tvalid_reg ? s_axis_tkeep_reg : s_axis_tkeep; + end else begin + m_axis_tdata_reg[seg_reg*SEG_DATA_WIDTH +: SEG_DATA_WIDTH] <= s_axis_tdata; + m_axis_tkeep_reg[seg_reg*SEG_KEEP_WIDTH +: SEG_KEEP_WIDTH] <= s_axis_tkeep; + end + m_axis_tlast_reg <= s_axis_tvalid_reg ? s_axis_tlast_reg : s_axis_tlast; + m_axis_tid_reg <= s_axis_tvalid_reg ? s_axis_tid_reg : s_axis_tid; + m_axis_tdest_reg <= s_axis_tvalid_reg ? s_axis_tdest_reg : s_axis_tdest; + m_axis_tuser_reg <= s_axis_tvalid_reg ? s_axis_tuser_reg : s_axis_tuser; + + if (s_axis_tvalid_reg) begin + // consume data from buffer + s_axis_tvalid_reg <= 1'b0; + + if (s_axis_tlast_reg || seg_reg == SEG_COUNT-1) begin + seg_reg <= 0; + m_axis_tvalid_reg <= 1'b1; + end else begin + seg_reg <= seg_reg + 1; + end + end else if (s_axis_tvalid) begin + // data direct from input + if (s_axis_tlast || seg_reg == SEG_COUNT-1) begin + seg_reg <= 0; + m_axis_tvalid_reg <= 1'b1; + end else begin + seg_reg <= seg_reg + 1; + end + end + end else if (s_axis_tvalid && s_axis_tready) begin + // store input data in skid buffer + s_axis_tdata_reg <= s_axis_tdata; + s_axis_tkeep_reg <= s_axis_tkeep; + s_axis_tvalid_reg <= 1'b1; + s_axis_tlast_reg <= s_axis_tlast; + s_axis_tid_reg <= s_axis_tid; + s_axis_tdest_reg <= s_axis_tdest; + s_axis_tuser_reg <= s_axis_tuser; + end + + if (rst) begin + seg_reg <= 0; + s_axis_tvalid_reg <= 1'b0; + m_axis_tvalid_reg <= 1'b0; + end + end + +end else begin : downsize + // output is narrower; downsize + + // required number of segments in wider bus + localparam SEG_COUNT = S_BYTE_LANES / M_BYTE_LANES; + // data width and keep width per segment + localparam SEG_DATA_WIDTH = S_DATA_WIDTH / SEG_COUNT; + localparam SEG_KEEP_WIDTH = S_BYTE_LANES / SEG_COUNT; + + reg [S_DATA_WIDTH-1:0] s_axis_tdata_reg = {S_DATA_WIDTH{1'b0}}; + reg [S_KEEP_WIDTH-1:0] s_axis_tkeep_reg = {S_KEEP_WIDTH{1'b0}}; + reg s_axis_tvalid_reg = 1'b0; + reg s_axis_tlast_reg = 1'b0; + reg [ID_WIDTH-1:0] s_axis_tid_reg = {ID_WIDTH{1'b0}}; + reg [DEST_WIDTH-1:0] s_axis_tdest_reg = {DEST_WIDTH{1'b0}}; + reg [USER_WIDTH-1:0] s_axis_tuser_reg = {USER_WIDTH{1'b0}}; + + reg [M_DATA_WIDTH-1:0] m_axis_tdata_reg = {M_DATA_WIDTH{1'b0}}; + reg [M_KEEP_WIDTH-1:0] m_axis_tkeep_reg = {M_KEEP_WIDTH{1'b0}}; + reg m_axis_tvalid_reg = 1'b0; + reg m_axis_tlast_reg = 1'b0; + reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; + reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; + reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + + assign s_axis_tready = !s_axis_tvalid_reg; + + assign m_axis_tdata = m_axis_tdata_reg; + assign m_axis_tkeep = M_KEEP_ENABLE ? m_axis_tkeep_reg : {M_KEEP_WIDTH{1'b1}}; + assign m_axis_tvalid = m_axis_tvalid_reg; + assign m_axis_tlast = m_axis_tlast_reg; + assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; + assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; + assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; + + always @(posedge clk) begin + m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready; + + if (!m_axis_tvalid_reg || m_axis_tready) begin + // output register empty + + m_axis_tdata_reg <= s_axis_tvalid_reg ? s_axis_tdata_reg : s_axis_tdata; + m_axis_tkeep_reg <= s_axis_tvalid_reg ? s_axis_tkeep_reg : s_axis_tkeep; + m_axis_tlast_reg <= 1'b0; + m_axis_tid_reg <= s_axis_tvalid_reg ? s_axis_tid_reg : s_axis_tid; + m_axis_tdest_reg <= s_axis_tvalid_reg ? s_axis_tdest_reg : s_axis_tdest; + m_axis_tuser_reg <= s_axis_tvalid_reg ? s_axis_tuser_reg : s_axis_tuser; + + if (s_axis_tvalid_reg) begin + // buffer has data; shift out from buffer + s_axis_tdata_reg <= s_axis_tdata_reg >> SEG_DATA_WIDTH; + s_axis_tkeep_reg <= s_axis_tkeep_reg >> SEG_KEEP_WIDTH; + + m_axis_tvalid_reg <= 1'b1; + + if ((s_axis_tkeep_reg >> SEG_KEEP_WIDTH) == 0) begin + s_axis_tvalid_reg <= 1'b0; + m_axis_tlast_reg <= s_axis_tlast_reg; + end + end else if (s_axis_tvalid && s_axis_tready) begin + // buffer is empty; store from input + s_axis_tdata_reg <= s_axis_tdata >> SEG_DATA_WIDTH; + s_axis_tkeep_reg <= s_axis_tkeep >> SEG_KEEP_WIDTH; + s_axis_tlast_reg <= s_axis_tlast; + s_axis_tid_reg <= s_axis_tid; + s_axis_tdest_reg <= s_axis_tdest; + s_axis_tuser_reg <= s_axis_tuser; + + m_axis_tvalid_reg <= 1'b1; + + if ((s_axis_tkeep >> SEG_KEEP_WIDTH) == 0) begin + s_axis_tvalid_reg <= 1'b0; + m_axis_tlast_reg <= s_axis_tlast; + end else begin + s_axis_tvalid_reg <= 1'b1; + end + end + end else if (s_axis_tvalid && s_axis_tready) begin + // store input data + s_axis_tdata_reg <= s_axis_tdata; + s_axis_tkeep_reg <= s_axis_tkeep; + s_axis_tvalid_reg <= 1'b1; + s_axis_tlast_reg <= s_axis_tlast; + s_axis_tid_reg <= s_axis_tid; + s_axis_tdest_reg <= s_axis_tdest; + s_axis_tuser_reg <= s_axis_tuser; + end + + if (rst) begin + s_axis_tvalid_reg <= 1'b0; + m_axis_tvalid_reg <= 1'b0; + end + end + +end + +endgenerate + +endmodule + +`resetall diff --git a/src/rvvi/axis_async_fifo.sv b/src/rvvi/axis_async_fifo.sv new file mode 100644 index 000000000..1d8b6244f --- /dev/null +++ b/src/rvvi/axis_async_fifo.sv @@ -0,0 +1,909 @@ +/* + +Copyright (c) 2014-2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * AXI4-Stream asynchronous FIFO + */ +module axis_async_fifo # +( + // FIFO depth in words + // KEEP_WIDTH words per cycle if KEEP_ENABLE set + // Rounded up to nearest power of 2 cycles + parameter DEPTH = 4096, + // Width of AXI stream interfaces in bits + parameter DATA_WIDTH = 8, + // Propagate tkeep signal + // If disabled, tkeep assumed to be 1'b1 + parameter KEEP_ENABLE = (DATA_WIDTH>8), + // tkeep signal width (words per cycle) + parameter KEEP_WIDTH = ((DATA_WIDTH+7)/8), + // Propagate tlast signal + parameter LAST_ENABLE = 1, + // Propagate tid signal + parameter ID_ENABLE = 0, + // tid signal width + parameter ID_WIDTH = 8, + // Propagate tdest signal + parameter DEST_ENABLE = 0, + // tdest signal width + parameter DEST_WIDTH = 8, + // Propagate tuser signal + parameter USER_ENABLE = 1, + // tuser signal width + parameter USER_WIDTH = 1, + // number of RAM pipeline registers + parameter RAM_PIPELINE = 1, + // use output FIFO + // When set, the RAM read enable and pipeline clock enables are removed + parameter OUTPUT_FIFO_ENABLE = 0, + // Frame FIFO mode - operate on frames instead of cycles + // When set, m_axis_tvalid will not be deasserted within a frame + // Requires LAST_ENABLE set + parameter FRAME_FIFO = 0, + // tuser value for bad frame marker + parameter USER_BAD_FRAME_VALUE = 1'b1, + // tuser mask for bad frame marker + parameter USER_BAD_FRAME_MASK = 1'b1, + // Drop frames larger than FIFO + // Requires FRAME_FIFO set + parameter DROP_OVERSIZE_FRAME = FRAME_FIFO, + // Drop frames marked bad + // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set + parameter DROP_BAD_FRAME = 0, + // Drop incoming frames when full + // When set, s_axis_tready is always asserted + // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set + parameter DROP_WHEN_FULL = 0, + // Mark incoming frames as bad frames when full + // When set, s_axis_tready is always asserted + // Requires FRAME_FIFO to be clear + parameter MARK_WHEN_FULL = 0, + // Enable pause request input + parameter PAUSE_ENABLE = 0, + // Pause between frames + parameter FRAME_PAUSE = FRAME_FIFO +) +( + /* + * AXI input + */ + input wire s_clk, + input wire s_rst, + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire [KEEP_WIDTH-1:0] s_axis_tkeep, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire [ID_WIDTH-1:0] s_axis_tid, + input wire [DEST_WIDTH-1:0] s_axis_tdest, + input wire [USER_WIDTH-1:0] s_axis_tuser, + + /* + * AXI output + */ + input wire m_clk, + input wire m_rst, + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire [KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire [ID_WIDTH-1:0] m_axis_tid, + output wire [DEST_WIDTH-1:0] m_axis_tdest, + output wire [USER_WIDTH-1:0] m_axis_tuser, + + /* + * Pause + */ + input wire s_pause_req, + output wire s_pause_ack, + input wire m_pause_req, + output wire m_pause_ack, + + /* + * Status + */ + output wire [$clog2(DEPTH):0] s_status_depth, + output wire [$clog2(DEPTH):0] s_status_depth_commit, + output wire s_status_overflow, + output wire s_status_bad_frame, + output wire s_status_good_frame, + output wire [$clog2(DEPTH):0] m_status_depth, + output wire [$clog2(DEPTH):0] m_status_depth_commit, + output wire m_status_overflow, + output wire m_status_bad_frame, + output wire m_status_good_frame +); + +parameter ADDR_WIDTH = (KEEP_ENABLE && KEEP_WIDTH > 1) ? $clog2(DEPTH/KEEP_WIDTH) : $clog2(DEPTH); + +parameter OUTPUT_FIFO_ADDR_WIDTH = RAM_PIPELINE < 2 ? 3 : $clog2(RAM_PIPELINE*2+7); + +// check configuration +initial begin + if (FRAME_FIFO && !LAST_ENABLE) begin + $error("Error: FRAME_FIFO set requires LAST_ENABLE set (instance %m)"); + $finish; + end + + if (DROP_OVERSIZE_FRAME && !FRAME_FIFO) begin + $error("Error: DROP_OVERSIZE_FRAME set requires FRAME_FIFO set (instance %m)"); + $finish; + end + + if (DROP_BAD_FRAME && !(FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin + $error("Error: DROP_BAD_FRAME set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)"); + $finish; + end + + if (DROP_WHEN_FULL && !(FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin + $error("Error: DROP_WHEN_FULL set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)"); + $finish; + end + + if ((DROP_BAD_FRAME || MARK_WHEN_FULL) && (USER_BAD_FRAME_MASK & {USER_WIDTH{1'b1}}) == 0) begin + $error("Error: Invalid USER_BAD_FRAME_MASK value (instance %m)"); + $finish; + end + + if (MARK_WHEN_FULL && FRAME_FIFO) begin + $error("Error: MARK_WHEN_FULL is not compatible with FRAME_FIFO (instance %m)"); + $finish; + end + + if (MARK_WHEN_FULL && !LAST_ENABLE) begin + $error("Error: MARK_WHEN_FULL set requires LAST_ENABLE set (instance %m)"); + $finish; + end +end + +localparam KEEP_OFFSET = DATA_WIDTH; +localparam LAST_OFFSET = KEEP_OFFSET + (KEEP_ENABLE ? KEEP_WIDTH : 0); +localparam ID_OFFSET = LAST_OFFSET + (LAST_ENABLE ? 1 : 0); +localparam DEST_OFFSET = ID_OFFSET + (ID_ENABLE ? ID_WIDTH : 0); +localparam USER_OFFSET = DEST_OFFSET + (DEST_ENABLE ? DEST_WIDTH : 0); +localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0); + +function [ADDR_WIDTH:0] bin2gray(input [ADDR_WIDTH:0] b); + bin2gray = b ^ (b >> 1); +endfunction + +function [ADDR_WIDTH:0] gray2bin(input [ADDR_WIDTH:0] g); + integer i; + for (i = 0; i <= ADDR_WIDTH; i = i + 1) begin + gray2bin[i] = ^(g >> i); + end +endfunction + +reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] wr_ptr_commit_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] wr_ptr_sync_commit_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] wr_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] rd_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; + +reg [ADDR_WIDTH:0] wr_ptr_temp; +reg [ADDR_WIDTH:0] rd_ptr_temp; + +(* SHREG_EXTRACT = "NO" *) +reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}}; +(* SHREG_EXTRACT = "NO" *) +reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}}; +(* SHREG_EXTRACT = "NO" *) +reg [ADDR_WIDTH:0] wr_ptr_commit_sync_reg = {ADDR_WIDTH+1{1'b0}}; +(* SHREG_EXTRACT = "NO" *) +reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}}; +(* SHREG_EXTRACT = "NO" *) +reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}}; + +reg wr_ptr_update_valid_reg = 1'b0; +reg wr_ptr_update_reg = 1'b0; +(* SHREG_EXTRACT = "NO" *) +reg wr_ptr_update_sync1_reg = 1'b0; +(* SHREG_EXTRACT = "NO" *) +reg wr_ptr_update_sync2_reg = 1'b0; +(* SHREG_EXTRACT = "NO" *) +reg wr_ptr_update_sync3_reg = 1'b0; +(* SHREG_EXTRACT = "NO" *) +reg wr_ptr_update_ack_sync1_reg = 1'b0; +(* SHREG_EXTRACT = "NO" *) +reg wr_ptr_update_ack_sync2_reg = 1'b0; + +(* SHREG_EXTRACT = "NO" *) +reg s_rst_sync1_reg = 1'b1; +(* SHREG_EXTRACT = "NO" *) +reg s_rst_sync2_reg = 1'b1; +(* SHREG_EXTRACT = "NO" *) +reg s_rst_sync3_reg = 1'b1; +(* SHREG_EXTRACT = "NO" *) +reg m_rst_sync1_reg = 1'b1; +(* SHREG_EXTRACT = "NO" *) +reg m_rst_sync2_reg = 1'b1; +(* SHREG_EXTRACT = "NO" *) +reg m_rst_sync3_reg = 1'b1; + +(* ramstyle = "no_rw_check" *) +reg [WIDTH-1:0] mem[(2**ADDR_WIDTH)-1:0]; +reg mem_read_data_valid_reg = 1'b0; + +(* shreg_extract = "no" *) +reg [WIDTH-1:0] m_axis_pipe_reg[RAM_PIPELINE+1-1:0]; +reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0; + +// full when first TWO MSBs do NOT match, but rest matches +// (gray code equivalent of first MSB different but rest same) +wire full = wr_ptr_gray_reg == (rd_ptr_gray_sync2_reg ^ {2'b11, {ADDR_WIDTH-1{1'b0}}}); +// empty when pointers match exactly +wire empty = FRAME_FIFO ? (rd_ptr_reg == wr_ptr_commit_sync_reg) : (rd_ptr_gray_reg == wr_ptr_gray_sync2_reg); +// overflow within packet +wire full_wr = wr_ptr_reg == (wr_ptr_commit_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}}); + +// control signals +reg write; +reg read; +reg store_output; + +reg s_frame_reg = 1'b0; +reg m_frame_reg = 1'b0; + +reg drop_frame_reg = 1'b0; +reg mark_frame_reg = 1'b0; +reg send_frame_reg = 1'b0; +reg overflow_reg = 1'b0; +reg bad_frame_reg = 1'b0; +reg good_frame_reg = 1'b0; + +reg m_drop_frame_reg = 1'b0; +reg m_terminate_frame_reg = 1'b0; + +reg [ADDR_WIDTH:0] s_depth_reg = 0; +reg [ADDR_WIDTH:0] s_depth_commit_reg = 0; +reg [ADDR_WIDTH:0] m_depth_reg = 0; +reg [ADDR_WIDTH:0] m_depth_commit_reg = 0; + +reg overflow_sync1_reg = 1'b0; +reg overflow_sync2_reg = 1'b0; +reg overflow_sync3_reg = 1'b0; +reg overflow_sync4_reg = 1'b0; +reg bad_frame_sync1_reg = 1'b0; +reg bad_frame_sync2_reg = 1'b0; +reg bad_frame_sync3_reg = 1'b0; +reg bad_frame_sync4_reg = 1'b0; +reg good_frame_sync1_reg = 1'b0; +reg good_frame_sync2_reg = 1'b0; +reg good_frame_sync3_reg = 1'b0; +reg good_frame_sync4_reg = 1'b0; + +assign s_axis_tready = (FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : (!full || MARK_WHEN_FULL)) && !s_rst_sync3_reg; + +wire [WIDTH-1:0] s_axis; + +generate + assign s_axis[DATA_WIDTH-1:0] = s_axis_tdata; + if (KEEP_ENABLE) assign s_axis[KEEP_OFFSET +: KEEP_WIDTH] = s_axis_tkeep; + if (LAST_ENABLE) assign s_axis[LAST_OFFSET] = s_axis_tlast | mark_frame_reg; + if (ID_ENABLE) assign s_axis[ID_OFFSET +: ID_WIDTH] = s_axis_tid; + if (DEST_ENABLE) assign s_axis[DEST_OFFSET +: DEST_WIDTH] = s_axis_tdest; + if (USER_ENABLE) assign s_axis[USER_OFFSET +: USER_WIDTH] = mark_frame_reg ? USER_BAD_FRAME_VALUE : s_axis_tuser; +endgenerate + +wire [WIDTH-1:0] m_axis = m_axis_pipe_reg[RAM_PIPELINE+1-1]; + +wire m_axis_tready_pipe; +wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1]; + +wire [DATA_WIDTH-1:0] m_axis_tdata_pipe = m_axis[DATA_WIDTH-1:0]; +wire [KEEP_WIDTH-1:0] m_axis_tkeep_pipe = KEEP_ENABLE ? m_axis[KEEP_OFFSET +: KEEP_WIDTH] : {KEEP_WIDTH{1'b1}}; +wire m_axis_tlast_pipe = LAST_ENABLE ? m_axis[LAST_OFFSET] | m_terminate_frame_reg : 1'b1; +wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis[ID_OFFSET +: ID_WIDTH] : {ID_WIDTH{1'b0}}; +wire [DEST_WIDTH-1:0] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}}; +wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? (m_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis[USER_OFFSET +: USER_WIDTH]) : {USER_WIDTH{1'b0}}; + +wire m_axis_tready_out; +wire m_axis_tvalid_out; + +wire [DATA_WIDTH-1:0] m_axis_tdata_out; +wire [KEEP_WIDTH-1:0] m_axis_tkeep_out; +wire m_axis_tlast_out; +wire [ID_WIDTH-1:0] m_axis_tid_out; +wire [DEST_WIDTH-1:0] m_axis_tdest_out; +wire [USER_WIDTH-1:0] m_axis_tuser_out; + +wire pipe_ready; + +assign s_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_reg; +assign s_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_commit_reg; +assign s_status_overflow = overflow_reg; +assign s_status_bad_frame = bad_frame_reg; +assign s_status_good_frame = good_frame_reg; + +assign m_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_reg; +assign m_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_commit_reg; +assign m_status_overflow = overflow_sync3_reg ^ overflow_sync4_reg; +assign m_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg; +assign m_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg; + +// reset synchronization +always @(posedge m_clk or posedge m_rst) begin + if (m_rst) begin + s_rst_sync1_reg <= 1'b1; + end else begin + s_rst_sync1_reg <= 1'b0; + end +end + +always @(posedge s_clk) begin + s_rst_sync2_reg <= s_rst_sync1_reg; + s_rst_sync3_reg <= s_rst_sync2_reg; +end + +always @(posedge s_clk or posedge s_rst) begin + if (s_rst) begin + m_rst_sync1_reg <= 1'b1; + end else begin + m_rst_sync1_reg <= 1'b0; + end +end + +always @(posedge m_clk) begin + m_rst_sync2_reg <= m_rst_sync1_reg; + m_rst_sync3_reg <= m_rst_sync2_reg; +end + +// Write logic +always @(posedge s_clk) begin + overflow_reg <= 1'b0; + bad_frame_reg <= 1'b0; + good_frame_reg <= 1'b0; + + if (FRAME_FIFO && wr_ptr_update_valid_reg) begin + // have updated pointer to sync + if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin + // no sync in progress; sync update + wr_ptr_update_valid_reg <= 1'b0; + wr_ptr_sync_commit_reg <= wr_ptr_commit_reg; + wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; + end + end + + if (s_axis_tready && s_axis_tvalid && LAST_ENABLE) begin + // track input frame status + s_frame_reg <= !s_axis_tlast; + end + + if (s_rst_sync3_reg && LAST_ENABLE) begin + // if sink side is reset during transfer, drop partial frame + if (s_frame_reg && !(s_axis_tready && s_axis_tvalid && s_axis_tlast)) begin + drop_frame_reg <= 1'b1; + end + if (s_axis_tready && s_axis_tvalid && !s_axis_tlast) begin + drop_frame_reg <= 1'b1; + end + end + + if (FRAME_FIFO) begin + // frame FIFO mode + if (s_axis_tready && s_axis_tvalid) begin + // transfer in + if ((full && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin + // full, packet overflow, or currently dropping frame + // drop frame + drop_frame_reg <= 1'b1; + if (s_axis_tlast) begin + // end of frame, reset write pointer + wr_ptr_temp = wr_ptr_commit_reg; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + drop_frame_reg <= 1'b0; + overflow_reg <= 1'b1; + end + end else begin + mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; + wr_ptr_temp = wr_ptr_reg + 1; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + if (s_axis_tlast || (!DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin + // end of frame or send frame + send_frame_reg <= !s_axis_tlast; + if (s_axis_tlast && DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~(s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin + // bad packet, reset write pointer + wr_ptr_temp = wr_ptr_commit_reg; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + bad_frame_reg <= 1'b1; + end else begin + // good packet or packet overflow, update write pointer + wr_ptr_temp = wr_ptr_reg + 1; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_commit_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + + if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin + // no sync in progress; sync update + wr_ptr_update_valid_reg <= 1'b0; + wr_ptr_sync_commit_reg <= wr_ptr_temp; + wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; + end else begin + // sync in progress; flag it for later + wr_ptr_update_valid_reg <= 1'b1; + end + + good_frame_reg <= s_axis_tlast; + end + end + end + end else if (s_axis_tvalid && full_wr && FRAME_FIFO && !DROP_OVERSIZE_FRAME) begin + // data valid with packet overflow + // update write pointer + send_frame_reg <= 1'b1; + wr_ptr_temp = wr_ptr_reg; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_commit_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + + if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin + // no sync in progress; sync update + wr_ptr_update_valid_reg <= 1'b0; + wr_ptr_sync_commit_reg <= wr_ptr_temp; + wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; + end else begin + // sync in progress; flag it for later + wr_ptr_update_valid_reg <= 1'b1; + end + end + end else begin + // normal FIFO mode + if (s_axis_tready && s_axis_tvalid) begin + if (drop_frame_reg && LAST_ENABLE) begin + // currently dropping frame + if (s_axis_tlast) begin + // end of frame + if (!full && mark_frame_reg && MARK_WHEN_FULL) begin + // terminate marked frame + mark_frame_reg <= 1'b0; + mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; + wr_ptr_temp = wr_ptr_reg + 1; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_commit_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + end + // end of frame, clear drop flag + drop_frame_reg <= 1'b0; + overflow_reg <= 1'b1; + end + end else if ((full || mark_frame_reg) && MARK_WHEN_FULL) begin + // full or marking frame + // drop frame; mark if this isn't the first cycle + drop_frame_reg <= 1'b1; + mark_frame_reg <= mark_frame_reg || s_frame_reg; + if (s_axis_tlast) begin + drop_frame_reg <= 1'b0; + overflow_reg <= 1'b1; + end + end else begin + // transfer in + mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; + wr_ptr_temp = wr_ptr_reg + 1; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_commit_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + end + end else if ((!full && !drop_frame_reg && mark_frame_reg) && MARK_WHEN_FULL) begin + // terminate marked frame + mark_frame_reg <= 1'b0; + mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; + wr_ptr_temp = wr_ptr_reg + 1; + wr_ptr_reg <= wr_ptr_temp; + wr_ptr_commit_reg <= wr_ptr_temp; + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); + end + end + + if (s_rst_sync3_reg) begin + wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}}; + + wr_ptr_update_valid_reg <= 1'b0; + wr_ptr_update_reg <= 1'b0; + end + + if (s_rst) begin + wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}}; + + wr_ptr_update_valid_reg <= 1'b0; + wr_ptr_update_reg <= 1'b0; + + s_frame_reg <= 1'b0; + + drop_frame_reg <= 1'b0; + mark_frame_reg <= 1'b0; + send_frame_reg <= 1'b0; + overflow_reg <= 1'b0; + bad_frame_reg <= 1'b0; + good_frame_reg <= 1'b0; + end +end + +// Write-side status +always @(posedge s_clk) begin + rd_ptr_conv_reg <= gray2bin(rd_ptr_gray_sync2_reg); + s_depth_reg <= wr_ptr_reg - rd_ptr_conv_reg; + s_depth_commit_reg <= wr_ptr_commit_reg - rd_ptr_conv_reg; +end + +// pointer synchronization +always @(posedge s_clk) begin + rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg; + rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg; + wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg; + wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg; + + if (s_rst) begin + rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; + rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_update_ack_sync1_reg <= 1'b0; + wr_ptr_update_ack_sync2_reg <= 1'b0; + end +end + +always @(posedge m_clk) begin + wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg; + wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg; + if (FRAME_FIFO && wr_ptr_update_sync2_reg ^ wr_ptr_update_sync3_reg) begin + wr_ptr_commit_sync_reg <= wr_ptr_sync_commit_reg; + end + wr_ptr_update_sync1_reg <= wr_ptr_update_reg; + wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg; + wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg; + + if (FRAME_FIFO && m_rst_sync3_reg) begin + wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; + end + + if (m_rst) begin + wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_commit_sync_reg <= {ADDR_WIDTH+1{1'b0}}; + wr_ptr_update_sync1_reg <= 1'b0; + wr_ptr_update_sync2_reg <= 1'b0; + wr_ptr_update_sync3_reg <= 1'b0; + end +end + +// status synchronization +always @(posedge s_clk) begin + overflow_sync1_reg <= overflow_sync1_reg ^ overflow_reg; + bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg; + good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg; + + if (s_rst) begin + overflow_sync1_reg <= 1'b0; + bad_frame_sync1_reg <= 1'b0; + good_frame_sync1_reg <= 1'b0; + end +end + +always @(posedge m_clk) begin + overflow_sync2_reg <= overflow_sync1_reg; + overflow_sync3_reg <= overflow_sync2_reg; + overflow_sync4_reg <= overflow_sync3_reg; + bad_frame_sync2_reg <= bad_frame_sync1_reg; + bad_frame_sync3_reg <= bad_frame_sync2_reg; + bad_frame_sync4_reg <= bad_frame_sync3_reg; + good_frame_sync2_reg <= good_frame_sync1_reg; + good_frame_sync3_reg <= good_frame_sync2_reg; + good_frame_sync4_reg <= good_frame_sync3_reg; + + if (m_rst) begin + overflow_sync2_reg <= 1'b0; + overflow_sync3_reg <= 1'b0; + overflow_sync4_reg <= 1'b0; + bad_frame_sync2_reg <= 1'b0; + bad_frame_sync3_reg <= 1'b0; + bad_frame_sync4_reg <= 1'b0; + good_frame_sync2_reg <= 1'b0; + good_frame_sync3_reg <= 1'b0; + good_frame_sync4_reg <= 1'b0; + end +end + +// Read logic +integer j; + +always @(posedge m_clk) begin + if (m_axis_tready_pipe) begin + // output ready; invalidate stage + m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b0; + m_terminate_frame_reg <= 1'b0; + end + + for (j = RAM_PIPELINE+1-1; j > 0; j = j - 1) begin + if (m_axis_tready_pipe || ((~m_axis_tvalid_pipe_reg) >> j)) begin + // output ready or bubble in pipeline; transfer down pipeline + m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j-1]; + m_axis_pipe_reg[j] <= m_axis_pipe_reg[j-1]; + m_axis_tvalid_pipe_reg[j-1] <= 1'b0; + end + end + + if (m_axis_tready_pipe || ~m_axis_tvalid_pipe_reg) begin + // output ready or bubble in pipeline; read new data from FIFO + m_axis_tvalid_pipe_reg[0] <= 1'b0; + m_axis_pipe_reg[0] <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]]; + if (!empty && !m_rst_sync3_reg && !m_drop_frame_reg && pipe_ready) begin + // not empty, increment pointer + m_axis_tvalid_pipe_reg[0] <= 1'b1; + rd_ptr_temp = rd_ptr_reg + 1; + rd_ptr_reg <= rd_ptr_temp; + rd_ptr_gray_reg <= rd_ptr_temp ^ (rd_ptr_temp >> 1); + end + end + + if (m_axis_tvalid_pipe && LAST_ENABLE) begin + // track output frame status + if (m_axis_tlast_pipe && m_axis_tready_pipe) begin + m_frame_reg <= 1'b0; + end else begin + m_frame_reg <= 1'b1; + end + end + + if (m_drop_frame_reg && (OUTPUT_FIFO_ENABLE ? pipe_ready : m_axis_tready_pipe || !m_axis_tvalid_pipe) && LAST_ENABLE) begin + // terminate frame + // (only for frame transfers interrupted by source reset) + m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b1; + m_terminate_frame_reg <= 1'b1; + m_drop_frame_reg <= 1'b0; + end + + if (m_rst_sync3_reg && LAST_ENABLE) begin + // if source side is reset during transfer, drop partial frame + + // empty output pipeline, except for last stage + if (RAM_PIPELINE > 0) begin + m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-2:0] <= 0; + end + + if (m_frame_reg && (!m_axis_tvalid_pipe || (m_axis_tvalid_pipe && !m_axis_tlast_pipe)) && + !(m_drop_frame_reg || m_terminate_frame_reg)) begin + // terminate frame + m_drop_frame_reg <= 1'b1; + end + end + + if (m_rst_sync3_reg) begin + rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; + rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; + end + + if (m_rst) begin + rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; + rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; + m_axis_tvalid_pipe_reg <= 0; + m_frame_reg <= 1'b0; + m_drop_frame_reg <= 1'b0; + m_terminate_frame_reg <= 1'b0; + end +end + +// Read-side status +always @(posedge m_clk) begin + wr_ptr_conv_reg <= gray2bin(wr_ptr_gray_sync2_reg); + m_depth_reg <= wr_ptr_conv_reg - rd_ptr_reg; + m_depth_commit_reg <= FRAME_FIFO ? wr_ptr_commit_sync_reg - rd_ptr_reg : wr_ptr_conv_reg - rd_ptr_reg; +end + +generate + +if (!OUTPUT_FIFO_ENABLE) begin + + assign pipe_ready = 1'b1; + + assign m_axis_tready_pipe = m_axis_tready_out; + assign m_axis_tvalid_out = m_axis_tvalid_pipe; + + assign m_axis_tdata_out = m_axis_tdata_pipe; + assign m_axis_tkeep_out = m_axis_tkeep_pipe; + assign m_axis_tlast_out = m_axis_tlast_pipe; + assign m_axis_tid_out = m_axis_tid_pipe; + assign m_axis_tdest_out = m_axis_tdest_pipe; + assign m_axis_tuser_out = m_axis_tuser_pipe; + +end else begin : output_fifo + + // output datapath logic + reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; + reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; + reg m_axis_tvalid_reg = 1'b0; + reg m_axis_tlast_reg = 1'b0; + reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; + reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; + reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + + reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0; + reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0; + reg out_fifo_half_full_reg = 1'b0; + + wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}}); + wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg; + + (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) + reg [DATA_WIDTH-1:0] out_fifo_tdata[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) + reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) + reg out_fifo_tlast[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) + reg [ID_WIDTH-1:0] out_fifo_tid[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) + reg [DEST_WIDTH-1:0] out_fifo_tdest[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) + reg [USER_WIDTH-1:0] out_fifo_tuser[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; + + assign pipe_ready = !out_fifo_half_full_reg; + + assign m_axis_tready_pipe = 1'b1; + + assign m_axis_tdata_out = m_axis_tdata_reg; + assign m_axis_tkeep_out = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; + assign m_axis_tvalid_out = m_axis_tvalid_reg; + assign m_axis_tlast_out = LAST_ENABLE ? m_axis_tlast_reg : 1'b1; + assign m_axis_tid_out = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; + assign m_axis_tdest_out = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; + assign m_axis_tuser_out = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; + + always @(posedge m_clk) begin + m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready_out; + + out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1); + + if (!out_fifo_full && m_axis_tvalid_pipe) begin + out_fifo_tdata[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_pipe; + out_fifo_tkeep[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_pipe; + out_fifo_tlast[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_pipe; + out_fifo_tid[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_pipe; + out_fifo_tdest[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_pipe; + out_fifo_tuser[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_pipe; + out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1; + end + + if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready_out)) begin + m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axis_tvalid_reg <= 1'b1; + m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; + out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1; + end + + if (m_rst) begin + out_fifo_wr_ptr_reg <= 0; + out_fifo_rd_ptr_reg <= 0; + m_axis_tvalid_reg <= 1'b0; + end + end + +end + +if (PAUSE_ENABLE) begin : pause + + // Pause logic + reg pause_reg = 1'b0; + reg pause_frame_reg = 1'b0; + + reg s_pause_req_sync1_reg; + reg s_pause_req_sync2_reg; + reg s_pause_req_sync3_reg; + reg s_pause_ack_sync1_reg; + reg s_pause_ack_sync2_reg; + reg s_pause_ack_sync3_reg; + + always @(posedge s_clk) begin + s_pause_req_sync1_reg <= s_pause_req; + s_pause_ack_sync2_reg <= s_pause_ack_sync1_reg; + s_pause_ack_sync3_reg <= s_pause_ack_sync2_reg; + end + + always @(posedge m_clk) begin + s_pause_req_sync2_reg <= s_pause_req_sync1_reg; + s_pause_req_sync3_reg <= s_pause_req_sync2_reg; + s_pause_ack_sync1_reg <= pause_reg; + end + + assign m_axis_tready_out = m_axis_tready && !pause_reg; + assign m_axis_tvalid = m_axis_tvalid_out && !pause_reg; + + assign m_axis_tdata = m_axis_tdata_out; + assign m_axis_tkeep = m_axis_tkeep_out; + assign m_axis_tlast = m_axis_tlast_out; + assign m_axis_tid = m_axis_tid_out; + assign m_axis_tdest = m_axis_tdest_out; + assign m_axis_tuser = m_axis_tuser_out; + + assign s_pause_ack = s_pause_ack_sync3_reg; + assign m_pause_ack = pause_reg; + + always @(posedge m_clk) begin + if (FRAME_PAUSE) begin + if (pause_reg) begin + // paused; update pause status + pause_reg <= m_pause_req || s_pause_req_sync3_reg; + end else if (m_axis_tvalid_out) begin + // frame transfer; set frame bit + pause_frame_reg <= 1'b1; + if (m_axis_tready && m_axis_tlast) begin + // end of frame; clear frame bit and update pause status + pause_frame_reg <= 1'b0; + pause_reg <= m_pause_req || s_pause_req_sync3_reg; + end + end else if (!pause_frame_reg) begin + // idle; update pause status + pause_reg <= m_pause_req || s_pause_req_sync3_reg; + end + end else begin + pause_reg <= m_pause_req || s_pause_req_sync3_reg; + end + + if (m_rst) begin + pause_frame_reg <= 1'b0; + pause_reg <= 1'b0; + end + end + +end else begin + + assign m_axis_tready_out = m_axis_tready; + assign m_axis_tvalid = m_axis_tvalid_out; + + assign m_axis_tdata = m_axis_tdata_out; + assign m_axis_tkeep = m_axis_tkeep_out; + assign m_axis_tlast = m_axis_tlast_out; + assign m_axis_tid = m_axis_tid_out; + assign m_axis_tdest = m_axis_tdest_out; + assign m_axis_tuser = m_axis_tuser_out; + + assign s_pause_ack = 1'b0; + assign m_pause_ack = 1'b0; + +end + +endgenerate + +endmodule + +`resetall diff --git a/src/rvvi/axis_async_fifo_adapter.sv b/src/rvvi/axis_async_fifo_adapter.sv new file mode 100644 index 000000000..d1e71b9fc --- /dev/null +++ b/src/rvvi/axis_async_fifo_adapter.sv @@ -0,0 +1,377 @@ +/* + +Copyright (c) 2019 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * AXI4-Stream asynchronous FIFO with width converter + */ +module axis_async_fifo_adapter # +( + // FIFO depth in words + // KEEP_WIDTH words per cycle if KEEP_ENABLE set + // Rounded up to nearest power of 2 cycles + parameter DEPTH = 4096, + // Width of input AXI stream interface in bits + parameter S_DATA_WIDTH = 8, + // Propagate tkeep signal on input interface + // If disabled, tkeep assumed to be 1'b1 + parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8), + // tkeep signal width (words per cycle) on input interface + parameter S_KEEP_WIDTH = ((S_DATA_WIDTH+7)/8), + // Width of output AXI stream interface in bits + parameter M_DATA_WIDTH = 8, + // Propagate tkeep signal on output interface + // If disabled, tkeep assumed to be 1'b1 + parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8), + // tkeep signal width (words per cycle) on output interface + parameter M_KEEP_WIDTH = ((M_DATA_WIDTH+7)/8), + // Propagate tid signal + parameter ID_ENABLE = 0, + // tid signal width + parameter ID_WIDTH = 8, + // Propagate tdest signal + parameter DEST_ENABLE = 0, + // tdest signal width + parameter DEST_WIDTH = 8, + // Propagate tuser signal + parameter USER_ENABLE = 1, + // tuser signal width + parameter USER_WIDTH = 1, + // number of RAM pipeline registers in FIFO + parameter RAM_PIPELINE = 1, + // use output FIFO + // When set, the RAM read enable and pipeline clock enables are removed + parameter OUTPUT_FIFO_ENABLE = 0, + // Frame FIFO mode - operate on frames instead of cycles + // When set, m_axis_tvalid will not be deasserted within a frame + // Requires LAST_ENABLE set + parameter FRAME_FIFO = 0, + // tuser value for bad frame marker + parameter USER_BAD_FRAME_VALUE = 1'b1, + // tuser mask for bad frame marker + parameter USER_BAD_FRAME_MASK = 1'b1, + // Drop frames larger than FIFO + // Requires FRAME_FIFO set + parameter DROP_OVERSIZE_FRAME = FRAME_FIFO, + // Drop frames marked bad + // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set + parameter DROP_BAD_FRAME = 0, + // Drop incoming frames when full + // When set, s_axis_tready is always asserted + // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set + parameter DROP_WHEN_FULL = 0, + // Mark incoming frames as bad frames when full + // When set, s_axis_tready is always asserted + // Requires FRAME_FIFO to be clear + parameter MARK_WHEN_FULL = 0, + // Enable pause request input + parameter PAUSE_ENABLE = 0, + // Pause between frames + parameter FRAME_PAUSE = FRAME_FIFO +) +( + /* + * AXI input + */ + input wire s_clk, + input wire s_rst, + input wire [S_DATA_WIDTH-1:0] s_axis_tdata, + input wire [S_KEEP_WIDTH-1:0] s_axis_tkeep, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire [ID_WIDTH-1:0] s_axis_tid, + input wire [DEST_WIDTH-1:0] s_axis_tdest, + input wire [USER_WIDTH-1:0] s_axis_tuser, + + /* + * AXI output + */ + input wire m_clk, + input wire m_rst, + output wire [M_DATA_WIDTH-1:0] m_axis_tdata, + output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire [ID_WIDTH-1:0] m_axis_tid, + output wire [DEST_WIDTH-1:0] m_axis_tdest, + output wire [USER_WIDTH-1:0] m_axis_tuser, + + /* + * Pause + */ + input wire s_pause_req, + output wire s_pause_ack, + input wire m_pause_req, + output wire m_pause_ack, + + /* + * Status + */ + output wire [$clog2(DEPTH):0] s_status_depth, + output wire [$clog2(DEPTH):0] s_status_depth_commit, + output wire s_status_overflow, + output wire s_status_bad_frame, + output wire s_status_good_frame, + output wire [$clog2(DEPTH):0] m_status_depth, + output wire [$clog2(DEPTH):0] m_status_depth_commit, + output wire m_status_overflow, + output wire m_status_bad_frame, + output wire m_status_good_frame +); + +// force keep width to 1 when disabled +localparam S_BYTE_LANES = S_KEEP_ENABLE ? S_KEEP_WIDTH : 1; +localparam M_BYTE_LANES = M_KEEP_ENABLE ? M_KEEP_WIDTH : 1; + +// bus byte sizes (must be identical) +localparam S_BYTE_SIZE = S_DATA_WIDTH / S_BYTE_LANES; +localparam M_BYTE_SIZE = M_DATA_WIDTH / M_BYTE_LANES; +// output bus is wider +localparam EXPAND_BUS = M_BYTE_LANES > S_BYTE_LANES; +// total data and keep widths +localparam DATA_WIDTH = EXPAND_BUS ? M_DATA_WIDTH : S_DATA_WIDTH; +localparam KEEP_WIDTH = EXPAND_BUS ? M_BYTE_LANES : S_BYTE_LANES; + +// bus width assertions +initial begin + if (S_BYTE_SIZE * S_BYTE_LANES != S_DATA_WIDTH) begin + $error("Error: input data width not evenly divisible (instance %m)"); + $finish; + end + + if (M_BYTE_SIZE * M_BYTE_LANES != M_DATA_WIDTH) begin + $error("Error: output data width not evenly divisible (instance %m)"); + $finish; + end + + if (S_BYTE_SIZE != M_BYTE_SIZE) begin + $error("Error: byte size mismatch (instance %m)"); + $finish; + end +end + +wire [DATA_WIDTH-1:0] pre_fifo_axis_tdata; +wire [KEEP_WIDTH-1:0] pre_fifo_axis_tkeep; +wire pre_fifo_axis_tvalid; +wire pre_fifo_axis_tready; +wire pre_fifo_axis_tlast; +wire [ID_WIDTH-1:0] pre_fifo_axis_tid; +wire [DEST_WIDTH-1:0] pre_fifo_axis_tdest; +wire [USER_WIDTH-1:0] pre_fifo_axis_tuser; + +wire [DATA_WIDTH-1:0] post_fifo_axis_tdata; +wire [KEEP_WIDTH-1:0] post_fifo_axis_tkeep; +wire post_fifo_axis_tvalid; +wire post_fifo_axis_tready; +wire post_fifo_axis_tlast; +wire [ID_WIDTH-1:0] post_fifo_axis_tid; +wire [DEST_WIDTH-1:0] post_fifo_axis_tdest; +wire [USER_WIDTH-1:0] post_fifo_axis_tuser; + +generate + +if (M_BYTE_LANES > S_BYTE_LANES) begin : upsize_pre + + // output wider, adapt width before FIFO + + axis_adapter #( + .S_DATA_WIDTH(S_DATA_WIDTH), + .S_KEEP_ENABLE(S_KEEP_ENABLE), + .S_KEEP_WIDTH(S_KEEP_WIDTH), + .M_DATA_WIDTH(M_DATA_WIDTH), + .M_KEEP_ENABLE(M_KEEP_ENABLE), + .M_KEEP_WIDTH(M_KEEP_WIDTH), + .ID_ENABLE(ID_ENABLE), + .ID_WIDTH(ID_WIDTH), + .DEST_ENABLE(DEST_ENABLE), + .DEST_WIDTH(DEST_WIDTH), + .USER_ENABLE(USER_ENABLE), + .USER_WIDTH(USER_WIDTH) + ) + adapter_inst ( + .clk(s_clk), + .rst(s_rst), + // AXI input + .s_axis_tdata(s_axis_tdata), + .s_axis_tkeep(s_axis_tkeep), + .s_axis_tvalid(s_axis_tvalid), + .s_axis_tready(s_axis_tready), + .s_axis_tlast(s_axis_tlast), + .s_axis_tid(s_axis_tid), + .s_axis_tdest(s_axis_tdest), + .s_axis_tuser(s_axis_tuser), + // AXI output + .m_axis_tdata(pre_fifo_axis_tdata), + .m_axis_tkeep(pre_fifo_axis_tkeep), + .m_axis_tvalid(pre_fifo_axis_tvalid), + .m_axis_tready(pre_fifo_axis_tready), + .m_axis_tlast(pre_fifo_axis_tlast), + .m_axis_tid(pre_fifo_axis_tid), + .m_axis_tdest(pre_fifo_axis_tdest), + .m_axis_tuser(pre_fifo_axis_tuser) + ); + +end else begin : bypass_pre + + assign pre_fifo_axis_tdata = s_axis_tdata; + assign pre_fifo_axis_tkeep = s_axis_tkeep; + assign pre_fifo_axis_tvalid = s_axis_tvalid; + assign s_axis_tready = pre_fifo_axis_tready; + assign pre_fifo_axis_tlast = s_axis_tlast; + assign pre_fifo_axis_tid = s_axis_tid; + assign pre_fifo_axis_tdest = s_axis_tdest; + assign pre_fifo_axis_tuser = s_axis_tuser; + +end + +axis_async_fifo #( + .DEPTH(DEPTH), + .DATA_WIDTH(DATA_WIDTH), + .KEEP_ENABLE(EXPAND_BUS ? M_KEEP_ENABLE : S_KEEP_ENABLE), + .KEEP_WIDTH(KEEP_WIDTH), + .LAST_ENABLE(1), + .ID_ENABLE(ID_ENABLE), + .ID_WIDTH(ID_WIDTH), + .DEST_ENABLE(DEST_ENABLE), + .DEST_WIDTH(DEST_WIDTH), + .USER_ENABLE(USER_ENABLE), + .USER_WIDTH(USER_WIDTH), + .RAM_PIPELINE(RAM_PIPELINE), + .OUTPUT_FIFO_ENABLE(OUTPUT_FIFO_ENABLE), + .FRAME_FIFO(FRAME_FIFO), + .USER_BAD_FRAME_VALUE(USER_BAD_FRAME_VALUE), + .USER_BAD_FRAME_MASK(USER_BAD_FRAME_MASK), + .DROP_OVERSIZE_FRAME(DROP_OVERSIZE_FRAME), + .DROP_BAD_FRAME(DROP_BAD_FRAME), + .DROP_WHEN_FULL(DROP_WHEN_FULL), + .MARK_WHEN_FULL(MARK_WHEN_FULL), + .PAUSE_ENABLE(PAUSE_ENABLE), + .FRAME_PAUSE(FRAME_PAUSE) +) +fifo_inst ( + // AXI input + .s_clk(s_clk), + .s_rst(s_rst), + .s_axis_tdata(pre_fifo_axis_tdata), + .s_axis_tkeep(pre_fifo_axis_tkeep), + .s_axis_tvalid(pre_fifo_axis_tvalid), + .s_axis_tready(pre_fifo_axis_tready), + .s_axis_tlast(pre_fifo_axis_tlast), + .s_axis_tid(pre_fifo_axis_tid), + .s_axis_tdest(pre_fifo_axis_tdest), + .s_axis_tuser(pre_fifo_axis_tuser), + // AXI output + .m_clk(m_clk), + .m_rst(m_rst), + .m_axis_tdata(post_fifo_axis_tdata), + .m_axis_tkeep(post_fifo_axis_tkeep), + .m_axis_tvalid(post_fifo_axis_tvalid), + .m_axis_tready(post_fifo_axis_tready), + .m_axis_tlast(post_fifo_axis_tlast), + .m_axis_tid(post_fifo_axis_tid), + .m_axis_tdest(post_fifo_axis_tdest), + .m_axis_tuser(post_fifo_axis_tuser), + // Pause + .s_pause_req(s_pause_req), + .s_pause_ack(s_pause_ack), + .m_pause_req(m_pause_req), + .m_pause_ack(m_pause_ack), + // Status + .s_status_depth(s_status_depth), + .s_status_depth_commit(s_status_depth_commit), + .s_status_overflow(s_status_overflow), + .s_status_bad_frame(s_status_bad_frame), + .s_status_good_frame(s_status_good_frame), + .m_status_depth(m_status_depth), + .m_status_depth_commit(m_status_depth_commit), + .m_status_overflow(m_status_overflow), + .m_status_bad_frame(m_status_bad_frame), + .m_status_good_frame(m_status_good_frame) +); + +if (M_BYTE_LANES < S_BYTE_LANES) begin : downsize_post + + // input wider, adapt width after FIFO + + axis_adapter #( + .S_DATA_WIDTH(S_DATA_WIDTH), + .S_KEEP_ENABLE(S_KEEP_ENABLE), + .S_KEEP_WIDTH(S_KEEP_WIDTH), + .M_DATA_WIDTH(M_DATA_WIDTH), + .M_KEEP_ENABLE(M_KEEP_ENABLE), + .M_KEEP_WIDTH(M_KEEP_WIDTH), + .ID_ENABLE(ID_ENABLE), + .ID_WIDTH(ID_WIDTH), + .DEST_ENABLE(DEST_ENABLE), + .DEST_WIDTH(DEST_WIDTH), + .USER_ENABLE(USER_ENABLE), + .USER_WIDTH(USER_WIDTH) + ) + adapter_inst ( + .clk(m_clk), + .rst(m_rst), + // AXI input + .s_axis_tdata(post_fifo_axis_tdata), + .s_axis_tkeep(post_fifo_axis_tkeep), + .s_axis_tvalid(post_fifo_axis_tvalid), + .s_axis_tready(post_fifo_axis_tready), + .s_axis_tlast(post_fifo_axis_tlast), + .s_axis_tid(post_fifo_axis_tid), + .s_axis_tdest(post_fifo_axis_tdest), + .s_axis_tuser(post_fifo_axis_tuser), + // AXI output + .m_axis_tdata(m_axis_tdata), + .m_axis_tkeep(m_axis_tkeep), + .m_axis_tvalid(m_axis_tvalid), + .m_axis_tready(m_axis_tready), + .m_axis_tlast(m_axis_tlast), + .m_axis_tid(m_axis_tid), + .m_axis_tdest(m_axis_tdest), + .m_axis_tuser(m_axis_tuser) + ); + +end else begin : bypass_post + + assign m_axis_tdata = post_fifo_axis_tdata; + assign m_axis_tkeep = post_fifo_axis_tkeep; + assign m_axis_tvalid = post_fifo_axis_tvalid; + assign post_fifo_axis_tready = m_axis_tready; + assign m_axis_tlast = post_fifo_axis_tlast; + assign m_axis_tid = post_fifo_axis_tid; + assign m_axis_tdest = post_fifo_axis_tdest; + assign m_axis_tuser = post_fifo_axis_tuser; + +end + +endgenerate + +endmodule + +`resetall diff --git a/src/rvvi/axis_gmii_rx.sv b/src/rvvi/axis_gmii_rx.sv new file mode 100644 index 000000000..037fce77a --- /dev/null +++ b/src/rvvi/axis_gmii_rx.sv @@ -0,0 +1,357 @@ +/* + +Copyright (c) 2015-2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * AXI4-Stream GMII frame receiver (GMII in, AXI out) + */ +module axis_gmii_rx # +( + parameter DATA_WIDTH = 8, + parameter PTP_TS_ENABLE = 0, + parameter PTP_TS_WIDTH = 96, + parameter USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1 +) +( + input wire clk, + input wire rst, + + /* + * GMII input + */ + input wire [DATA_WIDTH-1:0] gmii_rxd, + input wire gmii_rx_dv, + input wire gmii_rx_er, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire m_axis_tvalid, + output wire m_axis_tlast, + output wire [USER_WIDTH-1:0] m_axis_tuser, + + /* + * PTP + */ + input wire [PTP_TS_WIDTH-1:0] ptp_ts, + + /* + * Control + */ + input wire clk_enable, + input wire mii_select, + + /* + * Configuration + */ + input wire cfg_rx_enable, + + /* + * Status + */ + output wire start_packet, + output wire error_bad_frame, + output wire error_bad_fcs +); + +// bus width assertions +initial begin + if (DATA_WIDTH != 8) begin + $error("Error: Interface width must be 8"); + $finish; + end +end + +localparam [7:0] + ETH_PRE = 8'h55, + ETH_SFD = 8'hD5; + +localparam [2:0] + STATE_IDLE = 3'd0, + STATE_PAYLOAD = 3'd1, + STATE_WAIT_LAST = 3'd2; + +reg [2:0] state_reg = STATE_IDLE, state_next; + +// datapath control signals +reg reset_crc; +reg update_crc; + +reg mii_odd = 1'b0; +reg in_frame = 1'b0; + +reg [DATA_WIDTH-1:0] gmii_rxd_d0 = {DATA_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] gmii_rxd_d1 = {DATA_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] gmii_rxd_d2 = {DATA_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] gmii_rxd_d3 = {DATA_WIDTH{1'b0}}; +reg [DATA_WIDTH-1:0] gmii_rxd_d4 = {DATA_WIDTH{1'b0}}; + +reg gmii_rx_dv_d0 = 1'b0; +reg gmii_rx_dv_d1 = 1'b0; +reg gmii_rx_dv_d2 = 1'b0; +reg gmii_rx_dv_d3 = 1'b0; +reg gmii_rx_dv_d4 = 1'b0; + +reg gmii_rx_er_d0 = 1'b0; +reg gmii_rx_er_d1 = 1'b0; +reg gmii_rx_er_d2 = 1'b0; +reg gmii_rx_er_d3 = 1'b0; +reg gmii_rx_er_d4 = 1'b0; + +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}, m_axis_tdata_next; +reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; +reg m_axis_tlast_reg = 1'b0, m_axis_tlast_next; +reg m_axis_tuser_reg = 1'b0, m_axis_tuser_next; + +reg start_packet_int_reg = 1'b0; +reg start_packet_reg = 1'b0; +reg error_bad_frame_reg = 1'b0, error_bad_frame_next; +reg error_bad_fcs_reg = 1'b0, error_bad_fcs_next; + +reg [PTP_TS_WIDTH-1:0] ptp_ts_reg = 0; + +reg [31:0] crc_state = 32'hFFFFFFFF; +wire [31:0] crc_next; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tvalid = m_axis_tvalid_reg; +assign m_axis_tlast = m_axis_tlast_reg; +assign m_axis_tuser = PTP_TS_ENABLE ? {ptp_ts_reg, m_axis_tuser_reg} : m_axis_tuser_reg; + +assign start_packet = start_packet_reg; +assign error_bad_frame = error_bad_frame_reg; +assign error_bad_fcs = error_bad_fcs_reg; + +lfsr #( + .LFSR_WIDTH(32), + .LFSR_POLY(32'h4c11db7), + .LFSR_CONFIG("GALOIS"), + .LFSR_FEED_FORWARD(0), + .REVERSE(1), + .DATA_WIDTH(8), + .STYLE("AUTO") +) +eth_crc_8 ( + .data_in(gmii_rxd_d4), + .state_in(crc_state), + .data_out(), + .state_out(crc_next) +); + +always @* begin + state_next = STATE_IDLE; + + reset_crc = 1'b0; + update_crc = 1'b0; + + m_axis_tdata_next = {DATA_WIDTH{1'b0}}; + m_axis_tvalid_next = 1'b0; + m_axis_tlast_next = 1'b0; + m_axis_tuser_next = 1'b0; + + error_bad_frame_next = 1'b0; + error_bad_fcs_next = 1'b0; + + if (!clk_enable) begin + // clock disabled - hold state + state_next = state_reg; + end else if (mii_select && !mii_odd) begin + // MII even cycle - hold state + state_next = state_reg; + end else begin + case (state_reg) + STATE_IDLE: begin + // idle state - wait for packet + reset_crc = 1'b1; + + if (gmii_rx_dv_d4 && !gmii_rx_er_d4 && gmii_rxd_d4 == ETH_SFD && cfg_rx_enable) begin + state_next = STATE_PAYLOAD; + end else begin + state_next = STATE_IDLE; + end + end + STATE_PAYLOAD: begin + // read payload + update_crc = 1'b1; + + m_axis_tdata_next = gmii_rxd_d4; + m_axis_tvalid_next = 1'b1; + + if (gmii_rx_dv_d4 && gmii_rx_er_d4) begin + // error + m_axis_tlast_next = 1'b1; + m_axis_tuser_next = 1'b1; + error_bad_frame_next = 1'b1; + state_next = STATE_WAIT_LAST; + end else if (!gmii_rx_dv) begin + // end of packet + m_axis_tlast_next = 1'b1; + if (gmii_rx_er_d0 || gmii_rx_er_d1 || gmii_rx_er_d2 || gmii_rx_er_d3) begin + // error received in FCS bytes + m_axis_tuser_next = 1'b1; + error_bad_frame_next = 1'b1; + end else if ({gmii_rxd_d0, gmii_rxd_d1, gmii_rxd_d2, gmii_rxd_d3} == ~crc_next) begin + // FCS good + m_axis_tuser_next = 1'b0; + end else begin + // FCS bad + m_axis_tuser_next = 1'b1; + error_bad_frame_next = 1'b1; + error_bad_fcs_next = 1'b1; + end + state_next = STATE_IDLE; + end else begin + state_next = STATE_PAYLOAD; + end + end + STATE_WAIT_LAST: begin + // wait for end of packet + + if (~gmii_rx_dv) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_WAIT_LAST; + end + end + endcase + end +end + +always @(posedge clk) begin + state_reg <= state_next; + + m_axis_tdata_reg <= m_axis_tdata_next; + m_axis_tvalid_reg <= m_axis_tvalid_next; + m_axis_tlast_reg <= m_axis_tlast_next; + m_axis_tuser_reg <= m_axis_tuser_next; + + start_packet_int_reg <= 1'b0; + start_packet_reg <= 1'b0; + + if (start_packet_int_reg) begin + ptp_ts_reg <= ptp_ts; + start_packet_reg <= 1'b1; + end + + if (clk_enable) begin + if (mii_select) begin + mii_odd <= !mii_odd; + + if (in_frame) begin + in_frame <= gmii_rx_dv; + end else if (gmii_rx_dv && {gmii_rxd[3:0], gmii_rxd_d0[7:4]} == ETH_SFD) begin + in_frame <= 1'b1; + start_packet_int_reg <= 1'b1; + mii_odd <= 1'b1; + end + + gmii_rxd_d0 <= {gmii_rxd[3:0], gmii_rxd_d0[7:4]}; + + if (mii_odd) begin + gmii_rxd_d1 <= gmii_rxd_d0; + gmii_rxd_d2 <= gmii_rxd_d1; + gmii_rxd_d3 <= gmii_rxd_d2; + gmii_rxd_d4 <= gmii_rxd_d3; + + gmii_rx_dv_d0 <= gmii_rx_dv & gmii_rx_dv_d0; + gmii_rx_dv_d1 <= gmii_rx_dv_d0 & gmii_rx_dv; + gmii_rx_dv_d2 <= gmii_rx_dv_d1 & gmii_rx_dv; + gmii_rx_dv_d3 <= gmii_rx_dv_d2 & gmii_rx_dv; + gmii_rx_dv_d4 <= gmii_rx_dv_d3 & gmii_rx_dv; + + gmii_rx_er_d0 <= gmii_rx_er | gmii_rx_er_d0; + gmii_rx_er_d1 <= gmii_rx_er_d0; + gmii_rx_er_d2 <= gmii_rx_er_d1; + gmii_rx_er_d3 <= gmii_rx_er_d2; + gmii_rx_er_d4 <= gmii_rx_er_d3; + end else begin + gmii_rx_dv_d0 <= gmii_rx_dv; + gmii_rx_er_d0 <= gmii_rx_er; + end + end else begin + if (in_frame) begin + in_frame <= gmii_rx_dv; + end else if (gmii_rx_dv && gmii_rxd == ETH_SFD) begin + in_frame <= 1'b1; + start_packet_int_reg <= 1'b1; + end + + gmii_rxd_d0 <= gmii_rxd; + gmii_rxd_d1 <= gmii_rxd_d0; + gmii_rxd_d2 <= gmii_rxd_d1; + gmii_rxd_d3 <= gmii_rxd_d2; + gmii_rxd_d4 <= gmii_rxd_d3; + + gmii_rx_dv_d0 <= gmii_rx_dv; + gmii_rx_dv_d1 <= gmii_rx_dv_d0 & gmii_rx_dv; + gmii_rx_dv_d2 <= gmii_rx_dv_d1 & gmii_rx_dv; + gmii_rx_dv_d3 <= gmii_rx_dv_d2 & gmii_rx_dv; + gmii_rx_dv_d4 <= gmii_rx_dv_d3 & gmii_rx_dv; + + gmii_rx_er_d0 <= gmii_rx_er; + gmii_rx_er_d1 <= gmii_rx_er_d0; + gmii_rx_er_d2 <= gmii_rx_er_d1; + gmii_rx_er_d3 <= gmii_rx_er_d2; + gmii_rx_er_d4 <= gmii_rx_er_d3; + end + end + + if (reset_crc) begin + crc_state <= 32'hFFFFFFFF; + end else if (update_crc) begin + crc_state <= crc_next; + end + + error_bad_frame_reg <= error_bad_frame_next; + error_bad_fcs_reg <= error_bad_fcs_next; + + if (rst) begin + state_reg <= STATE_IDLE; + + m_axis_tvalid_reg <= 1'b0; + + start_packet_int_reg <= 1'b0; + start_packet_reg <= 1'b0; + error_bad_frame_reg <= 1'b0; + error_bad_fcs_reg <= 1'b0; + + in_frame <= 1'b0; + mii_odd <= 1'b0; + + gmii_rx_dv_d0 <= 1'b0; + gmii_rx_dv_d1 <= 1'b0; + gmii_rx_dv_d2 <= 1'b0; + gmii_rx_dv_d3 <= 1'b0; + gmii_rx_dv_d4 <= 1'b0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/axis_gmii_tx.sv b/src/rvvi/axis_gmii_tx.sv new file mode 100644 index 000000000..f2936039f --- /dev/null +++ b/src/rvvi/axis_gmii_tx.sv @@ -0,0 +1,457 @@ +/* + +Copyright (c) 2015-2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * AXI4-Stream GMII frame transmitter (AXI in, GMII out) + */ +module axis_gmii_tx # +( + parameter DATA_WIDTH = 8, + parameter ENABLE_PADDING = 1, + parameter MIN_FRAME_LENGTH = 64, + parameter PTP_TS_ENABLE = 0, + parameter PTP_TS_WIDTH = 96, + parameter PTP_TS_CTRL_IN_TUSER = 0, + parameter PTP_TAG_ENABLE = PTP_TS_ENABLE, + parameter PTP_TAG_WIDTH = 16, + parameter USER_WIDTH = (PTP_TS_ENABLE ? (PTP_TAG_ENABLE ? PTP_TAG_WIDTH : 0) + (PTP_TS_CTRL_IN_TUSER ? 1 : 0) : 0) + 1 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire [USER_WIDTH-1:0] s_axis_tuser, + + /* + * GMII output + */ + output wire [DATA_WIDTH-1:0] gmii_txd, + output wire gmii_tx_en, + output wire gmii_tx_er, + + /* + * PTP + */ + input wire [PTP_TS_WIDTH-1:0] ptp_ts, + output wire [PTP_TS_WIDTH-1:0] m_axis_ptp_ts, + output wire [PTP_TAG_WIDTH-1:0] m_axis_ptp_ts_tag, + output wire m_axis_ptp_ts_valid, + + /* + * Control + */ + input wire clk_enable, + input wire mii_select, + + /* + * Configuration + */ + input wire [7:0] cfg_ifg, + input wire cfg_tx_enable, + + /* + * Status + */ + output wire start_packet, + output wire error_underflow +); + +parameter MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-1+1); + +// bus width assertions +initial begin + if (DATA_WIDTH != 8) begin + $error("Error: Interface width must be 8"); + $finish; + end +end + +localparam [7:0] + ETH_PRE = 8'h55, + ETH_SFD = 8'hD5; + +localparam [2:0] + STATE_IDLE = 3'd0, + STATE_PREAMBLE = 3'd1, + STATE_PAYLOAD = 3'd2, + STATE_LAST = 3'd3, + STATE_PAD = 3'd4, + STATE_FCS = 3'd5, + STATE_IFG = 3'd6; + +reg [2:0] state_reg = STATE_IDLE, state_next; + +// datapath control signals +reg reset_crc; +reg update_crc; + +reg [7:0] s_tdata_reg = 8'd0, s_tdata_next; + +reg mii_odd_reg = 1'b0, mii_odd_next; +reg [3:0] mii_msn_reg = 4'b0, mii_msn_next; + +reg frame_reg = 1'b0, frame_next; +reg frame_error_reg = 1'b0, frame_error_next; +reg [7:0] frame_ptr_reg = 0, frame_ptr_next; +reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; + +reg [7:0] gmii_txd_reg = 8'd0, gmii_txd_next; +reg gmii_tx_en_reg = 1'b0, gmii_tx_en_next; +reg gmii_tx_er_reg = 1'b0, gmii_tx_er_next; + +reg s_axis_tready_reg = 1'b0, s_axis_tready_next; + +reg [PTP_TS_WIDTH-1:0] m_axis_ptp_ts_reg = 0, m_axis_ptp_ts_next; +reg [PTP_TAG_WIDTH-1:0] m_axis_ptp_ts_tag_reg = 0, m_axis_ptp_ts_tag_next; +reg m_axis_ptp_ts_valid_reg = 1'b0, m_axis_ptp_ts_valid_next; + +reg start_packet_int_reg = 1'b0, start_packet_int_next; +reg start_packet_reg = 1'b0, start_packet_next; +reg error_underflow_reg = 1'b0, error_underflow_next; + +reg [31:0] crc_state = 32'hFFFFFFFF; +wire [31:0] crc_next; + +assign s_axis_tready = s_axis_tready_reg; + +assign gmii_txd = gmii_txd_reg; +assign gmii_tx_en = gmii_tx_en_reg; +assign gmii_tx_er = gmii_tx_er_reg; + +assign m_axis_ptp_ts = PTP_TS_ENABLE ? m_axis_ptp_ts_reg : 0; +assign m_axis_ptp_ts_tag = PTP_TAG_ENABLE ? m_axis_ptp_ts_tag_reg : 0; +assign m_axis_ptp_ts_valid = PTP_TS_ENABLE || PTP_TAG_ENABLE ? m_axis_ptp_ts_valid_reg : 1'b0; + +assign start_packet = start_packet_reg; +assign error_underflow = error_underflow_reg; + +lfsr #( + .LFSR_WIDTH(32), + .LFSR_POLY(32'h4c11db7), + .LFSR_CONFIG("GALOIS"), + .LFSR_FEED_FORWARD(0), + .REVERSE(1), + .DATA_WIDTH(8), + .STYLE("AUTO") +) +eth_crc_8 ( + .data_in(s_tdata_reg), + .state_in(crc_state), + .data_out(), + .state_out(crc_next) +); + +always @* begin + state_next = STATE_IDLE; + + reset_crc = 1'b0; + update_crc = 1'b0; + + mii_odd_next = mii_odd_reg; + mii_msn_next = mii_msn_reg; + + frame_next = frame_reg; + frame_error_next = frame_error_reg; + frame_ptr_next = frame_ptr_reg; + frame_min_count_next = frame_min_count_reg; + + s_axis_tready_next = 1'b0; + + s_tdata_next = s_tdata_reg; + + m_axis_ptp_ts_next = m_axis_ptp_ts_reg; + m_axis_ptp_ts_tag_next = m_axis_ptp_ts_tag_reg; + m_axis_ptp_ts_valid_next = 1'b0; + + if (start_packet_reg && PTP_TS_ENABLE) begin + m_axis_ptp_ts_next = ptp_ts; + if (PTP_TS_CTRL_IN_TUSER) begin + m_axis_ptp_ts_tag_next = s_axis_tuser >> 2; + m_axis_ptp_ts_valid_next = s_axis_tuser[1]; + end else begin + m_axis_ptp_ts_tag_next = s_axis_tuser >> 1; + m_axis_ptp_ts_valid_next = 1'b1; + end + end + + gmii_txd_next = {DATA_WIDTH{1'b0}}; + gmii_tx_en_next = 1'b0; + gmii_tx_er_next = 1'b0; + + start_packet_int_next = start_packet_int_reg; + start_packet_next = 1'b0; + error_underflow_next = 1'b0; + + if (s_axis_tvalid && s_axis_tready) begin + frame_next = !s_axis_tlast; + end + + if (!clk_enable) begin + // clock disabled - hold state and outputs + gmii_txd_next = gmii_txd_reg; + gmii_tx_en_next = gmii_tx_en_reg; + gmii_tx_er_next = gmii_tx_er_reg; + state_next = state_reg; + end else if (mii_select && mii_odd_reg) begin + // MII odd cycle - hold state, output MSN + mii_odd_next = 1'b0; + gmii_txd_next = {4'd0, mii_msn_reg}; + gmii_tx_en_next = gmii_tx_en_reg; + gmii_tx_er_next = gmii_tx_er_reg; + state_next = state_reg; + if (start_packet_int_reg) begin + start_packet_int_next = 1'b0; + start_packet_next = 1'b1; + end + end else begin + case (state_reg) + STATE_IDLE: begin + // idle state - wait for packet + reset_crc = 1'b1; + + mii_odd_next = 1'b0; + frame_ptr_next = 1; + + frame_error_next = 1'b0; + frame_min_count_next = MIN_FRAME_LENGTH-4-1; + + if (s_axis_tvalid && cfg_tx_enable) begin + mii_odd_next = 1'b1; + gmii_txd_next = ETH_PRE; + gmii_tx_en_next = 1'b1; + state_next = STATE_PREAMBLE; + end else begin + state_next = STATE_IDLE; + end + end + STATE_PREAMBLE: begin + // send preamble + reset_crc = 1'b1; + + mii_odd_next = 1'b1; + frame_ptr_next = frame_ptr_reg + 1; + + gmii_txd_next = ETH_PRE; + gmii_tx_en_next = 1'b1; + + if (frame_ptr_reg == 6) begin + s_axis_tready_next = 1'b1; + s_tdata_next = s_axis_tdata; + state_next = STATE_PREAMBLE; + end else if (frame_ptr_reg == 7) begin + // end of preamble; start payload + frame_ptr_next = 0; + if (s_axis_tready_reg) begin + s_axis_tready_next = 1'b1; + s_tdata_next = s_axis_tdata; + end + gmii_txd_next = ETH_SFD; + if (mii_select) begin + start_packet_int_next = 1'b1; + end else begin + start_packet_next = 1'b1; + end + state_next = STATE_PAYLOAD; + end else begin + state_next = STATE_PREAMBLE; + end + end + STATE_PAYLOAD: begin + // send payload + + update_crc = 1'b1; + s_axis_tready_next = 1'b1; + + mii_odd_next = 1'b1; + + if (frame_min_count_reg) begin + frame_min_count_next = frame_min_count_reg - 1; + end + + gmii_txd_next = s_tdata_reg; + gmii_tx_en_next = 1'b1; + + s_tdata_next = s_axis_tdata; + + if (!s_axis_tvalid || s_axis_tlast) begin + s_axis_tready_next = frame_next; // drop frame + frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; + error_underflow_next = !s_axis_tvalid; + + state_next = STATE_LAST; + end else begin + state_next = STATE_PAYLOAD; + end + end + STATE_LAST: begin + // last payload word + + update_crc = 1'b1; + s_axis_tready_next = 1'b0; + + mii_odd_next = 1'b1; + + gmii_txd_next = s_tdata_reg; + gmii_tx_en_next = 1'b1; + + if (ENABLE_PADDING && frame_min_count_reg) begin + frame_min_count_next = frame_min_count_reg - 1; + s_tdata_next = 8'd0; + state_next = STATE_PAD; + end else begin + frame_ptr_next = 0; + state_next = STATE_FCS; + end + end + STATE_PAD: begin + // send padding + s_axis_tready_next = frame_next; // drop frame + + update_crc = 1'b1; + mii_odd_next = 1'b1; + + gmii_txd_next = 8'd0; + gmii_tx_en_next = 1'b1; + + s_tdata_next = 8'd0; + + if (frame_min_count_reg) begin + frame_min_count_next = frame_min_count_reg - 1; + state_next = STATE_PAD; + end else begin + frame_ptr_next = 0; + state_next = STATE_FCS; + end + end + STATE_FCS: begin + // send FCS + s_axis_tready_next = frame_next; // drop frame + + mii_odd_next = 1'b1; + frame_ptr_next = frame_ptr_reg + 1; + + case (frame_ptr_reg) + 2'd0: gmii_txd_next = ~crc_state[7:0]; + 2'd1: gmii_txd_next = ~crc_state[15:8]; + 2'd2: gmii_txd_next = ~crc_state[23:16]; + 2'd3: gmii_txd_next = ~crc_state[31:24]; + endcase + gmii_tx_en_next = 1'b1; + gmii_tx_er_next = frame_error_reg; + + if (frame_ptr_reg < 3) begin + state_next = STATE_FCS; + end else begin + frame_ptr_next = 0; + state_next = STATE_IFG; + end + end + STATE_IFG: begin + // send IFG + s_axis_tready_next = frame_next; // drop frame + + mii_odd_next = 1'b1; + frame_ptr_next = frame_ptr_reg + 1; + + if (frame_ptr_reg < cfg_ifg-1 || frame_reg) begin + state_next = STATE_IFG; + end else begin + state_next = STATE_IDLE; + end + end + endcase + + if (mii_select) begin + mii_msn_next = gmii_txd_next[7:4]; + gmii_txd_next[7:4] = 4'd0; + end + end +end + +always @(posedge clk) begin + state_reg <= state_next; + + frame_reg <= frame_next; + frame_error_reg <= frame_error_next; + frame_ptr_reg <= frame_ptr_next; + frame_min_count_reg <= frame_min_count_next; + + m_axis_ptp_ts_reg <= m_axis_ptp_ts_next; + m_axis_ptp_ts_tag_reg <= m_axis_ptp_ts_tag_next; + m_axis_ptp_ts_valid_reg <= m_axis_ptp_ts_valid_next; + + mii_odd_reg <= mii_odd_next; + mii_msn_reg <= mii_msn_next; + + s_tdata_reg <= s_tdata_next; + + s_axis_tready_reg <= s_axis_tready_next; + + gmii_txd_reg <= gmii_txd_next; + gmii_tx_en_reg <= gmii_tx_en_next; + gmii_tx_er_reg <= gmii_tx_er_next; + + if (reset_crc) begin + crc_state <= 32'hFFFFFFFF; + end else if (update_crc) begin + crc_state <= crc_next; + end + + start_packet_int_reg <= start_packet_int_next; + start_packet_reg <= start_packet_next; + error_underflow_reg <= error_underflow_next; + + if (rst) begin + state_reg <= STATE_IDLE; + + frame_reg <= 1'b0; + + s_axis_tready_reg <= 1'b0; + + m_axis_ptp_ts_valid_reg <= 1'b0; + + gmii_tx_en_reg <= 1'b0; + gmii_tx_er_reg <= 1'b0; + + start_packet_int_reg <= 1'b0; + start_packet_reg <= 1'b0; + error_underflow_reg <= 1'b0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/eth_axis_tx.sv b/src/rvvi/eth_axis_tx.sv new file mode 100644 index 000000000..b4287b281 --- /dev/null +++ b/src/rvvi/eth_axis_tx.sv @@ -0,0 +1,408 @@ +/* + +Copyright (c) 2014-2020 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * AXI4-Stream ethernet frame transmitter (Ethernet frame in, AXI out) + */ +module eth_axis_tx # +( + // Width of AXI stream interfaces in bits + parameter DATA_WIDTH = 8, + // Propagate tkeep signal + // If disabled, tkeep assumed to be 1'b1 + parameter KEEP_ENABLE = (DATA_WIDTH>8), + // tkeep signal width (words per cycle) + parameter KEEP_WIDTH = (DATA_WIDTH/8) +) +( + input wire clk, + input wire rst, + + /* + * Ethernet frame input + */ + input wire s_eth_hdr_valid, + output wire s_eth_hdr_ready, + input wire [47:0] s_eth_dest_mac, + input wire [47:0] s_eth_src_mac, + input wire [15:0] s_eth_type, + input wire [DATA_WIDTH-1:0] s_eth_payload_axis_tdata, + input wire [KEEP_WIDTH-1:0] s_eth_payload_axis_tkeep, + input wire s_eth_payload_axis_tvalid, + output wire s_eth_payload_axis_tready, + input wire s_eth_payload_axis_tlast, + input wire s_eth_payload_axis_tuser, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire [KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire m_axis_tuser, + + /* + * Status signals + */ + output wire busy +); + +parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; + +parameter HDR_SIZE = 14; + +parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; + +parameter PTR_WIDTH = $clog2(CYCLE_COUNT); + +parameter OFFSET = HDR_SIZE % BYTE_LANES; + +// bus width assertions +initial begin + if (BYTE_LANES * 8 != DATA_WIDTH) begin + $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); + $finish; + end +end + +/* + +Ethernet frame + + Field Length + Destination MAC address 6 octets + Source MAC address 6 octets + Ethertype 2 octets + +This module receives an Ethernet frame with header fields in parallel along +with the payload in an AXI stream, combines the header with the payload, and +transmits the complete Ethernet frame on the output AXI stream interface. + +*/ + +// datapath control signals +reg store_eth_hdr; + +reg send_eth_header_reg = 1'b0, send_eth_header_next; +reg send_eth_payload_reg = 1'b0, send_eth_payload_next; +reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; + +reg flush_save; +reg transfer_in_save; + +reg [47:0] eth_dest_mac_reg = 48'd0; +reg [47:0] eth_src_mac_reg = 48'd0; +reg [15:0] eth_type_reg = 16'd0; + +reg s_eth_hdr_ready_reg = 1'b0, s_eth_hdr_ready_next; +reg s_eth_payload_axis_tready_reg = 1'b0, s_eth_payload_axis_tready_next; + +reg busy_reg = 1'b0; + +reg [DATA_WIDTH-1:0] save_eth_payload_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] save_eth_payload_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg save_eth_payload_axis_tlast_reg = 1'b0; +reg save_eth_payload_axis_tuser_reg = 1'b0; + +reg [DATA_WIDTH-1:0] shift_eth_payload_axis_tdata; +reg [KEEP_WIDTH-1:0] shift_eth_payload_axis_tkeep; +reg shift_eth_payload_axis_tvalid; +reg shift_eth_payload_axis_tlast; +reg shift_eth_payload_axis_tuser; +reg shift_eth_payload_axis_input_tready; +reg shift_eth_payload_axis_extra_cycle_reg = 1'b0; + +// internal datapath +reg [DATA_WIDTH-1:0] m_axis_tdata_int; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; +reg m_axis_tvalid_int; +reg m_axis_tready_int_reg = 1'b0; +reg m_axis_tlast_int; +reg m_axis_tuser_int; +wire m_axis_tready_int_early; + +assign s_eth_hdr_ready = s_eth_hdr_ready_reg; +assign s_eth_payload_axis_tready = s_eth_payload_axis_tready_reg; + +assign busy = busy_reg; + +always @* begin + if (OFFSET == 0) begin + // passthrough if no overlap + shift_eth_payload_axis_tdata = s_eth_payload_axis_tdata; + shift_eth_payload_axis_tkeep = s_eth_payload_axis_tkeep; + shift_eth_payload_axis_tvalid = s_eth_payload_axis_tvalid; + shift_eth_payload_axis_tlast = s_eth_payload_axis_tlast; + shift_eth_payload_axis_tuser = s_eth_payload_axis_tuser; + shift_eth_payload_axis_input_tready = 1'b1; + end else if (shift_eth_payload_axis_extra_cycle_reg) begin + shift_eth_payload_axis_tdata = {s_eth_payload_axis_tdata, save_eth_payload_axis_tdata_reg} >> ((KEEP_WIDTH-OFFSET)*8); + shift_eth_payload_axis_tkeep = {{KEEP_WIDTH{1'b0}}, save_eth_payload_axis_tkeep_reg} >> (KEEP_WIDTH-OFFSET); + shift_eth_payload_axis_tvalid = 1'b1; + shift_eth_payload_axis_tlast = save_eth_payload_axis_tlast_reg; + shift_eth_payload_axis_tuser = save_eth_payload_axis_tuser_reg; + shift_eth_payload_axis_input_tready = flush_save; + end else begin + shift_eth_payload_axis_tdata = {s_eth_payload_axis_tdata, save_eth_payload_axis_tdata_reg} >> ((KEEP_WIDTH-OFFSET)*8); + shift_eth_payload_axis_tkeep = {s_eth_payload_axis_tkeep, save_eth_payload_axis_tkeep_reg} >> (KEEP_WIDTH-OFFSET); + shift_eth_payload_axis_tvalid = s_eth_payload_axis_tvalid; + shift_eth_payload_axis_tlast = (s_eth_payload_axis_tlast && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) == 0)); + shift_eth_payload_axis_tuser = (s_eth_payload_axis_tuser && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) == 0)); + shift_eth_payload_axis_input_tready = !(s_eth_payload_axis_tlast && s_eth_payload_axis_tready && s_eth_payload_axis_tvalid); + end +end + +always @* begin + send_eth_header_next = send_eth_header_reg; + send_eth_payload_next = send_eth_payload_reg; + ptr_next = ptr_reg; + + s_eth_hdr_ready_next = 1'b0; + s_eth_payload_axis_tready_next = 1'b0; + + store_eth_hdr = 1'b0; + + flush_save = 1'b0; + transfer_in_save = 1'b0; + + m_axis_tdata_int = {DATA_WIDTH{1'b0}}; + m_axis_tkeep_int = {KEEP_WIDTH{1'b0}}; + m_axis_tvalid_int = 1'b0; + m_axis_tlast_int = 1'b0; + m_axis_tuser_int = 1'b0; + + if (s_eth_hdr_ready && s_eth_hdr_valid) begin + store_eth_hdr = 1'b1; + ptr_next = 0; + send_eth_header_next = 1'b1; + send_eth_payload_next = (OFFSET != 0) && (CYCLE_COUNT == 1); + s_eth_payload_axis_tready_next = send_eth_payload_next && m_axis_tready_int_early; + end + + if (send_eth_payload_reg) begin + s_eth_payload_axis_tready_next = m_axis_tready_int_early && shift_eth_payload_axis_input_tready; + + m_axis_tdata_int = shift_eth_payload_axis_tdata; + m_axis_tkeep_int = shift_eth_payload_axis_tkeep; + m_axis_tlast_int = shift_eth_payload_axis_tlast; + m_axis_tuser_int = shift_eth_payload_axis_tuser; + + if ((s_eth_payload_axis_tready && s_eth_payload_axis_tvalid) || (m_axis_tready_int_reg && shift_eth_payload_axis_extra_cycle_reg)) begin + transfer_in_save = 1'b1; + + m_axis_tvalid_int = 1'b1; + + if (shift_eth_payload_axis_tlast) begin + flush_save = 1'b1; + s_eth_payload_axis_tready_next = 1'b0; + ptr_next = 0; + send_eth_payload_next = 1'b0; + end + end + end + + if (m_axis_tready_int_reg && (!OFFSET || !send_eth_payload_reg || m_axis_tvalid_int)) begin + if (send_eth_header_reg) begin + ptr_next = ptr_reg + 1; + + if ((OFFSET != 0) && (CYCLE_COUNT == 1 || ptr_next == CYCLE_COUNT-1) && !send_eth_payload_reg) begin + send_eth_payload_next = 1'b1; + s_eth_payload_axis_tready_next = m_axis_tready_int_early && shift_eth_payload_axis_input_tready; + end + + m_axis_tvalid_int = 1'b1; + + `define _HEADER_FIELD_(offset, field) \ + if (ptr_reg == offset/BYTE_LANES) begin \ + m_axis_tdata_int[(offset%BYTE_LANES)*8 +: 8] = field; \ + m_axis_tkeep_int[offset%BYTE_LANES] = 1'b1; \ + end + + `_HEADER_FIELD_(0, eth_dest_mac_reg[5*8 +: 8]) + `_HEADER_FIELD_(1, eth_dest_mac_reg[4*8 +: 8]) + `_HEADER_FIELD_(2, eth_dest_mac_reg[3*8 +: 8]) + `_HEADER_FIELD_(3, eth_dest_mac_reg[2*8 +: 8]) + `_HEADER_FIELD_(4, eth_dest_mac_reg[1*8 +: 8]) + `_HEADER_FIELD_(5, eth_dest_mac_reg[0*8 +: 8]) + `_HEADER_FIELD_(6, eth_src_mac_reg[5*8 +: 8]) + `_HEADER_FIELD_(7, eth_src_mac_reg[4*8 +: 8]) + `_HEADER_FIELD_(8, eth_src_mac_reg[3*8 +: 8]) + `_HEADER_FIELD_(9, eth_src_mac_reg[2*8 +: 8]) + `_HEADER_FIELD_(10, eth_src_mac_reg[1*8 +: 8]) + `_HEADER_FIELD_(11, eth_src_mac_reg[0*8 +: 8]) + `_HEADER_FIELD_(12, eth_type_reg[1*8 +: 8]) + `_HEADER_FIELD_(13, eth_type_reg[0*8 +: 8]) + + if (ptr_reg == 13/BYTE_LANES) begin + if (!send_eth_payload_reg) begin + s_eth_payload_axis_tready_next = m_axis_tready_int_early; + send_eth_payload_next = 1'b1; + end + send_eth_header_next = 1'b0; + end + + `undef _HEADER_FIELD_ + end + end + + s_eth_hdr_ready_next = !(send_eth_header_next || send_eth_payload_next); +end + +always @(posedge clk) begin + send_eth_header_reg <= send_eth_header_next; + send_eth_payload_reg <= send_eth_payload_next; + ptr_reg <= ptr_next; + + s_eth_hdr_ready_reg <= s_eth_hdr_ready_next; + s_eth_payload_axis_tready_reg <= s_eth_payload_axis_tready_next; + + busy_reg <= send_eth_header_next || send_eth_payload_next; + + if (store_eth_hdr) begin + eth_dest_mac_reg <= s_eth_dest_mac; + eth_src_mac_reg <= s_eth_src_mac; + eth_type_reg <= s_eth_type; + end + + if (transfer_in_save) begin + save_eth_payload_axis_tdata_reg <= s_eth_payload_axis_tdata; + save_eth_payload_axis_tkeep_reg <= s_eth_payload_axis_tkeep; + save_eth_payload_axis_tuser_reg <= s_eth_payload_axis_tuser; + end + + if (flush_save) begin + save_eth_payload_axis_tlast_reg <= 1'b0; + shift_eth_payload_axis_extra_cycle_reg <= 1'b0; + end else if (transfer_in_save) begin + save_eth_payload_axis_tlast_reg <= s_eth_payload_axis_tlast; + shift_eth_payload_axis_extra_cycle_reg <= OFFSET ? s_eth_payload_axis_tlast && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) != 0) : 1'b0; + end + + if (rst) begin + send_eth_header_reg <= 1'b0; + send_eth_payload_reg <= 1'b0; + ptr_reg <= 0; + s_eth_hdr_ready_reg <= 1'b0; + s_eth_payload_axis_tready_reg <= 1'b0; + busy_reg <= 1'b0; + end +end + +// output datapath logic +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; +reg m_axis_tlast_reg = 1'b0; +reg m_axis_tuser_reg = 1'b0; + +reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; +reg temp_m_axis_tlast_reg = 1'b0; +reg temp_m_axis_tuser_reg = 1'b0; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; +assign m_axis_tvalid = m_axis_tvalid_reg; +assign m_axis_tlast = m_axis_tlast_reg; +assign m_axis_tuser = m_axis_tuser_reg; + +// enable ready input next cycle if output is ready or if both output registers are empty +assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && !m_axis_tvalid_reg); + +always @* begin + // transfer sink ready state to source + m_axis_tvalid_next = m_axis_tvalid_reg; + temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (m_axis_tready_int_reg) begin + // input is ready + if (m_axis_tready || !m_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (m_axis_tready) begin + // input is not ready, but output is ready + m_axis_tvalid_next = temp_m_axis_tvalid_reg; + temp_m_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + m_axis_tvalid_reg <= m_axis_tvalid_next; + m_axis_tready_int_reg <= m_axis_tready_int_early; + temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; + + // datapath + if (store_axis_int_to_output) begin + m_axis_tdata_reg <= m_axis_tdata_int; + m_axis_tkeep_reg <= m_axis_tkeep_int; + m_axis_tlast_reg <= m_axis_tlast_int; + m_axis_tuser_reg <= m_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + m_axis_tdata_reg <= temp_m_axis_tdata_reg; + m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; + m_axis_tlast_reg <= temp_m_axis_tlast_reg; + m_axis_tuser_reg <= temp_m_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_m_axis_tdata_reg <= m_axis_tdata_int; + temp_m_axis_tkeep_reg <= m_axis_tkeep_int; + temp_m_axis_tlast_reg <= m_axis_tlast_int; + temp_m_axis_tuser_reg <= m_axis_tuser_int; + end + + if (rst) begin + m_axis_tvalid_reg <= 1'b0; + m_axis_tready_int_reg <= 1'b0; + temp_m_axis_tvalid_reg <= 1'b0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/eth_mac_1g.sv b/src/rvvi/eth_mac_1g.sv new file mode 100644 index 000000000..6e0592fac --- /dev/null +++ b/src/rvvi/eth_mac_1g.sv @@ -0,0 +1,643 @@ +/* + +Copyright (c) 2015-2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * 1G Ethernet MAC + */ +module eth_mac_1g # +( + parameter DATA_WIDTH = 8, + parameter ENABLE_PADDING = 1, + parameter MIN_FRAME_LENGTH = 64, + parameter PTP_TS_ENABLE = 0, + parameter PTP_TS_FMT_TOD = 1, + parameter PTP_TS_WIDTH = PTP_TS_FMT_TOD ? 96 : 64, + parameter TX_PTP_TS_CTRL_IN_TUSER = 0, + parameter TX_PTP_TAG_ENABLE = PTP_TS_ENABLE, + parameter TX_PTP_TAG_WIDTH = 16, + parameter TX_USER_WIDTH = (PTP_TS_ENABLE ? (TX_PTP_TAG_ENABLE ? TX_PTP_TAG_WIDTH : 0) + (TX_PTP_TS_CTRL_IN_TUSER ? 1 : 0) : 0) + 1, + parameter RX_USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1, + parameter PFC_ENABLE = 0, + parameter PAUSE_ENABLE = PFC_ENABLE +) +( + input wire rx_clk, + input wire rx_rst, + input wire tx_clk, + input wire tx_rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] tx_axis_tdata, + input wire tx_axis_tvalid, + output wire tx_axis_tready, + input wire tx_axis_tlast, + input wire [TX_USER_WIDTH-1:0] tx_axis_tuser, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] rx_axis_tdata, + output wire rx_axis_tvalid, + output wire rx_axis_tlast, + output wire [RX_USER_WIDTH-1:0] rx_axis_tuser, + + /* + * GMII interface + */ + input wire [DATA_WIDTH-1:0] gmii_rxd, + input wire gmii_rx_dv, + input wire gmii_rx_er, + output wire [DATA_WIDTH-1:0] gmii_txd, + output wire gmii_tx_en, + output wire gmii_tx_er, + + /* + * PTP + */ + input wire [PTP_TS_WIDTH-1:0] tx_ptp_ts, + input wire [PTP_TS_WIDTH-1:0] rx_ptp_ts, + output wire [PTP_TS_WIDTH-1:0] tx_axis_ptp_ts, + output wire [TX_PTP_TAG_WIDTH-1:0] tx_axis_ptp_ts_tag, + output wire tx_axis_ptp_ts_valid, + + /* + * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) + */ + input wire tx_lfc_req, + input wire tx_lfc_resend, + input wire rx_lfc_en, + output wire rx_lfc_req, + input wire rx_lfc_ack, + + /* + * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) + */ + input wire [7:0] tx_pfc_req, + input wire tx_pfc_resend, + input wire [7:0] rx_pfc_en, + output wire [7:0] rx_pfc_req, + input wire [7:0] rx_pfc_ack, + + /* + * Pause interface + */ + input wire tx_lfc_pause_en, + input wire tx_pause_req, + output wire tx_pause_ack, + + /* + * Control + */ + input wire rx_clk_enable, + input wire tx_clk_enable, + input wire rx_mii_select, + input wire tx_mii_select, + + /* + * Status + */ + output wire tx_start_packet, + output wire tx_error_underflow, + output wire rx_start_packet, + output wire rx_error_bad_frame, + output wire rx_error_bad_fcs, + output wire stat_tx_mcf, + output wire stat_rx_mcf, + output wire stat_tx_lfc_pkt, + output wire stat_tx_lfc_xon, + output wire stat_tx_lfc_xoff, + output wire stat_tx_lfc_paused, + output wire stat_tx_pfc_pkt, + output wire [7:0] stat_tx_pfc_xon, + output wire [7:0] stat_tx_pfc_xoff, + output wire [7:0] stat_tx_pfc_paused, + output wire stat_rx_lfc_pkt, + output wire stat_rx_lfc_xon, + output wire stat_rx_lfc_xoff, + output wire stat_rx_lfc_paused, + output wire stat_rx_pfc_pkt, + output wire [7:0] stat_rx_pfc_xon, + output wire [7:0] stat_rx_pfc_xoff, + output wire [7:0] stat_rx_pfc_paused, + + /* + * Configuration + */ + input wire [7:0] cfg_ifg, + input wire cfg_tx_enable, + input wire cfg_rx_enable, + input wire [47:0] cfg_mcf_rx_eth_dst_mcast, + input wire cfg_mcf_rx_check_eth_dst_mcast, + input wire [47:0] cfg_mcf_rx_eth_dst_ucast, + input wire cfg_mcf_rx_check_eth_dst_ucast, + input wire [47:0] cfg_mcf_rx_eth_src, + input wire cfg_mcf_rx_check_eth_src, + input wire [15:0] cfg_mcf_rx_eth_type, + input wire [15:0] cfg_mcf_rx_opcode_lfc, + input wire cfg_mcf_rx_check_opcode_lfc, + input wire [15:0] cfg_mcf_rx_opcode_pfc, + input wire cfg_mcf_rx_check_opcode_pfc, + input wire cfg_mcf_rx_forward, + input wire cfg_mcf_rx_enable, + input wire [47:0] cfg_tx_lfc_eth_dst, + input wire [47:0] cfg_tx_lfc_eth_src, + input wire [15:0] cfg_tx_lfc_eth_type, + input wire [15:0] cfg_tx_lfc_opcode, + input wire cfg_tx_lfc_en, + input wire [15:0] cfg_tx_lfc_quanta, + input wire [15:0] cfg_tx_lfc_refresh, + input wire [47:0] cfg_tx_pfc_eth_dst, + input wire [47:0] cfg_tx_pfc_eth_src, + input wire [15:0] cfg_tx_pfc_eth_type, + input wire [15:0] cfg_tx_pfc_opcode, + input wire cfg_tx_pfc_en, + input wire [8*16-1:0] cfg_tx_pfc_quanta, + input wire [8*16-1:0] cfg_tx_pfc_refresh, + input wire [15:0] cfg_rx_lfc_opcode, + input wire cfg_rx_lfc_en, + input wire [15:0] cfg_rx_pfc_opcode, + input wire cfg_rx_pfc_en +); + +parameter MAC_CTRL_ENABLE = PAUSE_ENABLE || PFC_ENABLE; +parameter TX_USER_WIDTH_INT = MAC_CTRL_ENABLE ? (PTP_TS_ENABLE ? (TX_PTP_TAG_ENABLE ? TX_PTP_TAG_WIDTH : 0) + 1 : 0) + 1 : TX_USER_WIDTH; + +wire [DATA_WIDTH-1:0] tx_axis_tdata_int; +wire tx_axis_tvalid_int; +wire tx_axis_tready_int; +wire tx_axis_tlast_int; +wire [TX_USER_WIDTH_INT-1:0] tx_axis_tuser_int; + +wire [DATA_WIDTH-1:0] rx_axis_tdata_int; +wire rx_axis_tvalid_int; +wire rx_axis_tlast_int; +wire [RX_USER_WIDTH-1:0] rx_axis_tuser_int; + +axis_gmii_rx #( + .DATA_WIDTH(DATA_WIDTH), + .PTP_TS_ENABLE(PTP_TS_ENABLE), + .PTP_TS_WIDTH(PTP_TS_WIDTH), + .USER_WIDTH(RX_USER_WIDTH) +) +axis_gmii_rx_inst ( + .clk(rx_clk), + .rst(rx_rst), + .gmii_rxd(gmii_rxd), + .gmii_rx_dv(gmii_rx_dv), + .gmii_rx_er(gmii_rx_er), + .m_axis_tdata(rx_axis_tdata_int), + .m_axis_tvalid(rx_axis_tvalid_int), + .m_axis_tlast(rx_axis_tlast_int), + .m_axis_tuser(rx_axis_tuser_int), + .ptp_ts(rx_ptp_ts), + .clk_enable(rx_clk_enable), + .mii_select(rx_mii_select), + .cfg_rx_enable(cfg_rx_enable), + .start_packet(rx_start_packet), + .error_bad_frame(rx_error_bad_frame), + .error_bad_fcs(rx_error_bad_fcs) +); + +axis_gmii_tx #( + .DATA_WIDTH(DATA_WIDTH), + .ENABLE_PADDING(ENABLE_PADDING), + .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH), + .PTP_TS_ENABLE(PTP_TS_ENABLE), + .PTP_TS_WIDTH(PTP_TS_WIDTH), + .PTP_TS_CTRL_IN_TUSER(MAC_CTRL_ENABLE ? PTP_TS_ENABLE : TX_PTP_TS_CTRL_IN_TUSER), + .PTP_TAG_ENABLE(TX_PTP_TAG_ENABLE), + .PTP_TAG_WIDTH(TX_PTP_TAG_WIDTH), + .USER_WIDTH(TX_USER_WIDTH_INT) +) +axis_gmii_tx_inst ( + .clk(tx_clk), + .rst(tx_rst), + .s_axis_tdata(tx_axis_tdata_int), + .s_axis_tvalid(tx_axis_tvalid_int), + .s_axis_tready(tx_axis_tready_int), + .s_axis_tlast(tx_axis_tlast_int), + .s_axis_tuser(tx_axis_tuser_int), + .gmii_txd(gmii_txd), + .gmii_tx_en(gmii_tx_en), + .gmii_tx_er(gmii_tx_er), + .ptp_ts(tx_ptp_ts), + .m_axis_ptp_ts(tx_axis_ptp_ts), + .m_axis_ptp_ts_tag(tx_axis_ptp_ts_tag), + .m_axis_ptp_ts_valid(tx_axis_ptp_ts_valid), + .clk_enable(tx_clk_enable), + .mii_select(tx_mii_select), + .cfg_ifg(cfg_ifg), + .cfg_tx_enable(cfg_tx_enable), + .start_packet(tx_start_packet), + .error_underflow(tx_error_underflow) +); + +generate + +if (MAC_CTRL_ENABLE) begin : mac_ctrl + + localparam MCF_PARAMS_SIZE = PFC_ENABLE ? 18 : 2; + + wire tx_mcf_valid; + wire tx_mcf_ready; + wire [47:0] tx_mcf_eth_dst; + wire [47:0] tx_mcf_eth_src; + wire [15:0] tx_mcf_eth_type; + wire [15:0] tx_mcf_opcode; + wire [MCF_PARAMS_SIZE*8-1:0] tx_mcf_params; + + wire rx_mcf_valid; + wire [47:0] rx_mcf_eth_dst; + wire [47:0] rx_mcf_eth_src; + wire [15:0] rx_mcf_eth_type; + wire [15:0] rx_mcf_opcode; + wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params; + + // terminate LFC pause requests from RX internally on TX side + wire tx_pause_req_int; + wire rx_lfc_ack_int; + + reg tx_lfc_req_sync_reg_1 = 1'b0; + reg tx_lfc_req_sync_reg_2 = 1'b0; + reg tx_lfc_req_sync_reg_3 = 1'b0; + + always @(posedge rx_clk or posedge rx_rst) begin + if (rx_rst) begin + tx_lfc_req_sync_reg_1 <= 1'b0; + end else begin + tx_lfc_req_sync_reg_1 <= rx_lfc_req; + end + end + + always @(posedge tx_clk or posedge tx_rst) begin + if (tx_rst) begin + tx_lfc_req_sync_reg_2 <= 1'b0; + tx_lfc_req_sync_reg_3 <= 1'b0; + end else begin + tx_lfc_req_sync_reg_2 <= tx_lfc_req_sync_reg_1; + tx_lfc_req_sync_reg_3 <= tx_lfc_req_sync_reg_2; + end + end + + reg rx_lfc_ack_sync_reg_1 = 1'b0; + reg rx_lfc_ack_sync_reg_2 = 1'b0; + reg rx_lfc_ack_sync_reg_3 = 1'b0; + + always @(posedge tx_clk or posedge tx_rst) begin + if (tx_rst) begin + rx_lfc_ack_sync_reg_1 <= 1'b0; + end else begin + rx_lfc_ack_sync_reg_1 <= tx_lfc_pause_en ? tx_pause_ack : 0; + end + end + + always @(posedge rx_clk or posedge rx_rst) begin + if (rx_rst) begin + rx_lfc_ack_sync_reg_2 <= 1'b0; + rx_lfc_ack_sync_reg_3 <= 1'b0; + end else begin + rx_lfc_ack_sync_reg_2 <= rx_lfc_ack_sync_reg_1; + rx_lfc_ack_sync_reg_3 <= rx_lfc_ack_sync_reg_2; + end + end + + assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en ? tx_lfc_req_sync_reg_3 : 0); + + assign rx_lfc_ack_int = rx_lfc_ack || rx_lfc_ack_sync_reg_3; + + // handle PTP TS enable bit in tuser + wire [TX_USER_WIDTH_INT-1:0] tx_axis_tuser_in; + + if (PTP_TS_ENABLE && !TX_PTP_TS_CTRL_IN_TUSER) begin + assign tx_axis_tuser_in = {tx_axis_tuser[TX_USER_WIDTH-1:1], 1'b1, tx_axis_tuser[0]}; + end else begin + assign tx_axis_tuser_in = tx_axis_tuser; + end + + mac_ctrl_tx #( + .DATA_WIDTH(DATA_WIDTH), + .KEEP_ENABLE(0), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(1), + .USER_WIDTH(TX_USER_WIDTH_INT), + .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE) + ) + mac_ctrl_tx_inst ( + .clk(tx_clk), + .rst(tx_rst), + + /* + * AXI stream input + */ + .s_axis_tdata(tx_axis_tdata), + .s_axis_tkeep(1'b1), + .s_axis_tvalid(tx_axis_tvalid), + .s_axis_tready(tx_axis_tready), + .s_axis_tlast(tx_axis_tlast), + .s_axis_tid(0), + .s_axis_tdest(0), + .s_axis_tuser(tx_axis_tuser_in), + + /* + * AXI stream output + */ + .m_axis_tdata(tx_axis_tdata_int), + .m_axis_tkeep(), + .m_axis_tvalid(tx_axis_tvalid_int), + .m_axis_tready(tx_axis_tready_int), + .m_axis_tlast(tx_axis_tlast_int), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(tx_axis_tuser_int), + + /* + * MAC control frame interface + */ + .mcf_valid(tx_mcf_valid), + .mcf_ready(tx_mcf_ready), + .mcf_eth_dst(tx_mcf_eth_dst), + .mcf_eth_src(tx_mcf_eth_src), + .mcf_eth_type(tx_mcf_eth_type), + .mcf_opcode(tx_mcf_opcode), + .mcf_params(tx_mcf_params), + .mcf_id(0), + .mcf_dest(0), + .mcf_user(0), + + /* + * Pause interface + */ + .tx_pause_req(tx_pause_req_int), + .tx_pause_ack(tx_pause_ack), + + /* + * Status + */ + .stat_tx_mcf(stat_tx_mcf) + ); + + mac_ctrl_rx #( + .DATA_WIDTH(DATA_WIDTH), + .KEEP_ENABLE(0), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(1), + .USER_WIDTH(RX_USER_WIDTH), + .USE_READY(0), + .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE) + ) + mac_ctrl_rx_inst ( + .clk(rx_clk), + .rst(rx_rst), + + /* + * AXI stream input + */ + .s_axis_tdata(rx_axis_tdata_int), + .s_axis_tkeep(1'b1), + .s_axis_tvalid(rx_axis_tvalid_int), + .s_axis_tready(), + .s_axis_tlast(rx_axis_tlast_int), + .s_axis_tid(0), + .s_axis_tdest(0), + .s_axis_tuser(rx_axis_tuser_int), + + /* + * AXI stream output + */ + .m_axis_tdata(rx_axis_tdata), + .m_axis_tkeep(), + .m_axis_tvalid(rx_axis_tvalid), + .m_axis_tready(1'b1), + .m_axis_tlast(rx_axis_tlast), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(rx_axis_tuser), + + /* + * MAC control frame interface + */ + .mcf_valid(rx_mcf_valid), + .mcf_eth_dst(rx_mcf_eth_dst), + .mcf_eth_src(rx_mcf_eth_src), + .mcf_eth_type(rx_mcf_eth_type), + .mcf_opcode(rx_mcf_opcode), + .mcf_params(rx_mcf_params), + .mcf_id(), + .mcf_dest(), + .mcf_user(), + + /* + * Configuration + */ + .cfg_mcf_rx_eth_dst_mcast(cfg_mcf_rx_eth_dst_mcast), + .cfg_mcf_rx_check_eth_dst_mcast(cfg_mcf_rx_check_eth_dst_mcast), + .cfg_mcf_rx_eth_dst_ucast(cfg_mcf_rx_eth_dst_ucast), + .cfg_mcf_rx_check_eth_dst_ucast(cfg_mcf_rx_check_eth_dst_ucast), + .cfg_mcf_rx_eth_src(cfg_mcf_rx_eth_src), + .cfg_mcf_rx_check_eth_src(cfg_mcf_rx_check_eth_src), + .cfg_mcf_rx_eth_type(cfg_mcf_rx_eth_type), + .cfg_mcf_rx_opcode_lfc(cfg_mcf_rx_opcode_lfc), + .cfg_mcf_rx_check_opcode_lfc(cfg_mcf_rx_check_opcode_lfc), + .cfg_mcf_rx_opcode_pfc(cfg_mcf_rx_opcode_pfc), + .cfg_mcf_rx_check_opcode_pfc(cfg_mcf_rx_check_opcode_pfc), + .cfg_mcf_rx_forward(cfg_mcf_rx_forward), + .cfg_mcf_rx_enable(cfg_mcf_rx_enable), + + /* + * Status + */ + .stat_rx_mcf(stat_rx_mcf) + ); + + mac_pause_ctrl_tx #( + .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE), + .PFC_ENABLE(PFC_ENABLE) + ) + mac_pause_ctrl_tx_inst ( + .clk(tx_clk), + .rst(tx_rst), + + /* + * MAC control frame interface + */ + .mcf_valid(tx_mcf_valid), + .mcf_ready(tx_mcf_ready), + .mcf_eth_dst(tx_mcf_eth_dst), + .mcf_eth_src(tx_mcf_eth_src), + .mcf_eth_type(tx_mcf_eth_type), + .mcf_opcode(tx_mcf_opcode), + .mcf_params(tx_mcf_params), + + /* + * Pause (IEEE 802.3 annex 31B) + */ + .tx_lfc_req(tx_lfc_req), + .tx_lfc_resend(tx_lfc_resend), + + /* + * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) + */ + .tx_pfc_req(tx_pfc_req), + .tx_pfc_resend(tx_pfc_resend), + + /* + * Configuration + */ + .cfg_tx_lfc_eth_dst(cfg_tx_lfc_eth_dst), + .cfg_tx_lfc_eth_src(cfg_tx_lfc_eth_src), + .cfg_tx_lfc_eth_type(cfg_tx_lfc_eth_type), + .cfg_tx_lfc_opcode(cfg_tx_lfc_opcode), + .cfg_tx_lfc_en(cfg_tx_lfc_en), + .cfg_tx_lfc_quanta(cfg_tx_lfc_quanta), + .cfg_tx_lfc_refresh(cfg_tx_lfc_refresh), + .cfg_tx_pfc_eth_dst(cfg_tx_pfc_eth_dst), + .cfg_tx_pfc_eth_src(cfg_tx_pfc_eth_src), + .cfg_tx_pfc_eth_type(cfg_tx_pfc_eth_type), + .cfg_tx_pfc_opcode(cfg_tx_pfc_opcode), + .cfg_tx_pfc_en(cfg_tx_pfc_en), + .cfg_tx_pfc_quanta(cfg_tx_pfc_quanta), + .cfg_tx_pfc_refresh(cfg_tx_pfc_refresh), + .cfg_quanta_step(tx_mii_select ? (4*256)/512 : (8*256)/512), + .cfg_quanta_clk_en(tx_clk_enable), + + /* + * Status + */ + .stat_tx_lfc_pkt(stat_tx_lfc_pkt), + .stat_tx_lfc_xon(stat_tx_lfc_xon), + .stat_tx_lfc_xoff(stat_tx_lfc_xoff), + .stat_tx_lfc_paused(stat_tx_lfc_paused), + .stat_tx_pfc_pkt(stat_tx_pfc_pkt), + .stat_tx_pfc_xon(stat_tx_pfc_xon), + .stat_tx_pfc_xoff(stat_tx_pfc_xoff), + .stat_tx_pfc_paused(stat_tx_pfc_paused) + ); + + mac_pause_ctrl_rx #( + .MCF_PARAMS_SIZE(18), + .PFC_ENABLE(PFC_ENABLE) + ) + mac_pause_ctrl_rx_inst ( + .clk(rx_clk), + .rst(rx_rst), + + /* + * MAC control frame interface + */ + .mcf_valid(rx_mcf_valid), + .mcf_eth_dst(rx_mcf_eth_dst), + .mcf_eth_src(rx_mcf_eth_src), + .mcf_eth_type(rx_mcf_eth_type), + .mcf_opcode(rx_mcf_opcode), + .mcf_params(rx_mcf_params), + + /* + * Pause (IEEE 802.3 annex 31B) + */ + .rx_lfc_en(rx_lfc_en), + .rx_lfc_req(rx_lfc_req), + .rx_lfc_ack(rx_lfc_ack_int), + + /* + * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) + */ + .rx_pfc_en(rx_pfc_en), + .rx_pfc_req(rx_pfc_req), + .rx_pfc_ack(rx_pfc_ack), + + /* + * Configuration + */ + .cfg_rx_lfc_opcode(cfg_rx_lfc_opcode), + .cfg_rx_lfc_en(cfg_rx_lfc_en), + .cfg_rx_pfc_opcode(cfg_rx_pfc_opcode), + .cfg_rx_pfc_en(cfg_rx_pfc_en), + .cfg_quanta_step(rx_mii_select ? (4*256)/512 : (8*256)/512), + .cfg_quanta_clk_en(rx_clk_enable), + + /* + * Status + */ + .stat_rx_lfc_pkt(stat_rx_lfc_pkt), + .stat_rx_lfc_xon(stat_rx_lfc_xon), + .stat_rx_lfc_xoff(stat_rx_lfc_xoff), + .stat_rx_lfc_paused(stat_rx_lfc_paused), + .stat_rx_pfc_pkt(stat_rx_pfc_pkt), + .stat_rx_pfc_xon(stat_rx_pfc_xon), + .stat_rx_pfc_xoff(stat_rx_pfc_xoff), + .stat_rx_pfc_paused(stat_rx_pfc_paused) + ); + +end else begin + + assign tx_axis_tdata_int = tx_axis_tdata; + assign tx_axis_tvalid_int = tx_axis_tvalid; + assign tx_axis_tready = tx_axis_tready_int; + assign tx_axis_tlast_int = tx_axis_tlast; + assign tx_axis_tuser_int = tx_axis_tuser; + + assign rx_axis_tdata = rx_axis_tdata_int; + assign rx_axis_tvalid = rx_axis_tvalid_int; + assign rx_axis_tlast = rx_axis_tlast_int; + assign rx_axis_tuser = rx_axis_tuser_int; + + assign rx_lfc_req = 0; + assign rx_pfc_req = 0; + assign tx_pause_ack = 0; + + assign stat_tx_mcf = 0; + assign stat_rx_mcf = 0; + assign stat_tx_lfc_pkt = 0; + assign stat_tx_lfc_xon = 0; + assign stat_tx_lfc_xoff = 0; + assign stat_tx_lfc_paused = 0; + assign stat_tx_pfc_pkt = 0; + assign stat_tx_pfc_xon = 0; + assign stat_tx_pfc_xoff = 0; + assign stat_tx_pfc_paused = 0; + assign stat_rx_lfc_pkt = 0; + assign stat_rx_lfc_xon = 0; + assign stat_rx_lfc_xoff = 0; + assign stat_rx_lfc_paused = 0; + assign stat_rx_pfc_pkt = 0; + assign stat_rx_pfc_xon = 0; + assign stat_rx_pfc_xoff = 0; + assign stat_rx_pfc_paused = 0; + +end + +endgenerate + +endmodule + +`resetall diff --git a/src/rvvi/eth_mac_mii.sv b/src/rvvi/eth_mac_mii.sv new file mode 100644 index 000000000..212f4b84a --- /dev/null +++ b/src/rvvi/eth_mac_mii.sv @@ -0,0 +1,175 @@ +/* + +Copyright (c) 2019 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * 10M/100M Ethernet MAC with MII interface + */ +module eth_mac_mii # +( + // target ("SIM", "GENERIC", "XILINX", "ALTERA") + parameter TARGET = "GENERIC", + // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") + // Use BUFR for Virtex-5, Virtex-6, 7-series + // Use BUFG for Ultrascale + // Use BUFIO2 for Spartan-6 + parameter CLOCK_INPUT_STYLE = "BUFIO2", + parameter ENABLE_PADDING = 1, + parameter MIN_FRAME_LENGTH = 64 +) +( + input wire rst, + output wire rx_clk, + output wire rx_rst, + output wire tx_clk, + output wire tx_rst, + + /* + * AXI input + */ + input wire [7:0] tx_axis_tdata, + input wire tx_axis_tvalid, + output wire tx_axis_tready, + input wire tx_axis_tlast, + input wire tx_axis_tuser, + + /* + * AXI output + */ + output wire [7:0] rx_axis_tdata, + output wire rx_axis_tvalid, + output wire rx_axis_tlast, + output wire rx_axis_tuser, + + /* + * MII interface + */ + input wire mii_rx_clk, + input wire [3:0] mii_rxd, + input wire mii_rx_dv, + input wire mii_rx_er, + input wire mii_tx_clk, + output wire [3:0] mii_txd, + output wire mii_tx_en, + output wire mii_tx_er, + + /* + * Status + */ + output wire tx_start_packet, + output wire tx_error_underflow, + output wire rx_start_packet, + output wire rx_error_bad_frame, + output wire rx_error_bad_fcs, + + /* + * Configuration + */ + input wire [7:0] cfg_ifg, + input wire cfg_tx_enable, + input wire cfg_rx_enable +); + +wire [3:0] mac_mii_rxd; +wire mac_mii_rx_dv; +wire mac_mii_rx_er; +wire [3:0] mac_mii_txd; +wire mac_mii_tx_en; +wire mac_mii_tx_er; + +mii_phy_if #( + .TARGET(TARGET), + .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE) +) +mii_phy_if_inst ( + .rst(rst), + + .mac_mii_rx_clk(rx_clk), + .mac_mii_rx_rst(rx_rst), + .mac_mii_rxd(mac_mii_rxd), + .mac_mii_rx_dv(mac_mii_rx_dv), + .mac_mii_rx_er(mac_mii_rx_er), + .mac_mii_tx_clk(tx_clk), + .mac_mii_tx_rst(tx_rst), + .mac_mii_txd(mac_mii_txd), + .mac_mii_tx_en(mac_mii_tx_en), + .mac_mii_tx_er(mac_mii_tx_er), + + .phy_mii_rx_clk(mii_rx_clk), + .phy_mii_rxd(mii_rxd), + .phy_mii_rx_dv(mii_rx_dv), + .phy_mii_rx_er(mii_rx_er), + .phy_mii_tx_clk(mii_tx_clk), + .phy_mii_txd(mii_txd), + .phy_mii_tx_en(mii_tx_en), + .phy_mii_tx_er(mii_tx_er) +); + // *** there a bunch of missing pins +/* verilator lint_off PINMISSING */ +eth_mac_1g #( + .ENABLE_PADDING(ENABLE_PADDING), + .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH) +) +eth_mac_1g_inst ( + .tx_clk(tx_clk), + .tx_rst(tx_rst), + .rx_clk(rx_clk), + .rx_rst(rx_rst), + .tx_axis_tdata(tx_axis_tdata), + .tx_axis_tvalid(tx_axis_tvalid), + .tx_axis_tready(tx_axis_tready), + .tx_axis_tlast(tx_axis_tlast), + .tx_axis_tuser(tx_axis_tuser), + .rx_axis_tdata(rx_axis_tdata), + .rx_axis_tvalid(rx_axis_tvalid), + .rx_axis_tlast(rx_axis_tlast), + .rx_axis_tuser(rx_axis_tuser), + .gmii_rxd(mac_mii_rxd), + .gmii_rx_dv(mac_mii_rx_dv), + .gmii_rx_er(mac_mii_rx_er), + .gmii_txd(mac_mii_txd), + .gmii_tx_en(mac_mii_tx_en), + .gmii_tx_er(mac_mii_tx_er), + .rx_clk_enable(1'b1), + .tx_clk_enable(1'b1), + .rx_mii_select(1'b1), + .tx_mii_select(1'b1), + .tx_start_packet(tx_start_packet), + .tx_error_underflow(tx_error_underflow), + .rx_start_packet(rx_start_packet), + .rx_error_bad_frame(rx_error_bad_frame), + .rx_error_bad_fcs(rx_error_bad_fcs), + .cfg_ifg(cfg_ifg), + .cfg_tx_enable(cfg_tx_enable), + .cfg_rx_enable(cfg_rx_enable) +); +/* verilator lint_on PINMISSING */ + +endmodule + +`resetall diff --git a/src/rvvi/eth_mac_mii_fifo.sv b/src/rvvi/eth_mac_mii_fifo.sv new file mode 100644 index 000000000..a285ceeed --- /dev/null +++ b/src/rvvi/eth_mac_mii_fifo.sv @@ -0,0 +1,339 @@ +/* + +Copyright (c) 2019 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * 10M/100M Ethernet MAC with MII interface and TX and RX FIFOs + */ +module eth_mac_mii_fifo # +( + // target ("SIM", "GENERIC", "XILINX", "ALTERA") + parameter TARGET = "GENERIC", + // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") + // Use BUFR for Virtex-5, Virtex-6, 7-series + // Use BUFG for Ultrascale + // Use BUFIO2 for Spartan-6 + parameter CLOCK_INPUT_STYLE = "BUFIO2", + parameter AXIS_DATA_WIDTH = 8, + parameter AXIS_KEEP_ENABLE = (AXIS_DATA_WIDTH>8), + parameter AXIS_KEEP_WIDTH = (AXIS_DATA_WIDTH/8), + parameter ENABLE_PADDING = 1, + parameter MIN_FRAME_LENGTH = 64, + parameter TX_FIFO_DEPTH = 4096, + parameter TX_FIFO_RAM_PIPELINE = 1, + parameter TX_FRAME_FIFO = 1, + parameter TX_DROP_OVERSIZE_FRAME = TX_FRAME_FIFO, + parameter TX_DROP_BAD_FRAME = TX_DROP_OVERSIZE_FRAME, + parameter TX_DROP_WHEN_FULL = 0, + parameter RX_FIFO_DEPTH = 4096, + parameter RX_FIFO_RAM_PIPELINE = 1, + parameter RX_FRAME_FIFO = 1, + parameter RX_DROP_OVERSIZE_FRAME = RX_FRAME_FIFO, + parameter RX_DROP_BAD_FRAME = RX_DROP_OVERSIZE_FRAME, + parameter RX_DROP_WHEN_FULL = RX_DROP_OVERSIZE_FRAME +) +( + input wire rst, + input wire logic_clk, + input wire logic_rst, + + /* + * AXI input + */ + input wire [AXIS_DATA_WIDTH-1:0] tx_axis_tdata, + input wire [AXIS_KEEP_WIDTH-1:0] tx_axis_tkeep, + input wire tx_axis_tvalid, + output wire tx_axis_tready, + input wire tx_axis_tlast, + input wire tx_axis_tuser, + + /* + * AXI output + */ + output wire [AXIS_DATA_WIDTH-1:0] rx_axis_tdata, + output wire [AXIS_KEEP_WIDTH-1:0] rx_axis_tkeep, + output wire rx_axis_tvalid, + input wire rx_axis_tready, + output wire rx_axis_tlast, + output wire rx_axis_tuser, + + /* + * MII interface + */ + input wire mii_rx_clk, + input wire [3:0] mii_rxd, + input wire mii_rx_dv, + input wire mii_rx_er, + input wire mii_tx_clk, + output wire [3:0] mii_txd, + output wire mii_tx_en, + output wire mii_tx_er, + + /* + * Status + */ + output wire tx_error_underflow, + output wire tx_fifo_overflow, + output wire tx_fifo_bad_frame, + output wire tx_fifo_good_frame, + output wire rx_error_bad_frame, + output wire rx_error_bad_fcs, + output wire rx_fifo_overflow, + output wire rx_fifo_bad_frame, + output wire rx_fifo_good_frame, + + /* + * Configuration + */ + input wire [7:0] cfg_ifg, + input wire cfg_tx_enable, + input wire cfg_rx_enable +); + +wire tx_clk; +wire rx_clk; +wire tx_rst; +wire rx_rst; + +wire [7:0] tx_fifo_axis_tdata; +wire tx_fifo_axis_tvalid; +wire tx_fifo_axis_tready; +wire tx_fifo_axis_tlast; +wire tx_fifo_axis_tuser; + +wire [7:0] rx_fifo_axis_tdata; +wire rx_fifo_axis_tvalid; +wire rx_fifo_axis_tlast; +wire rx_fifo_axis_tuser; + +// synchronize MAC status signals into logic clock domain +wire tx_error_underflow_int; + +reg [0:0] tx_sync_reg_1 = 1'b0; +reg [0:0] tx_sync_reg_2 = 1'b0; +reg [0:0] tx_sync_reg_3 = 1'b0; +reg [0:0] tx_sync_reg_4 = 1'b0; + +assign tx_error_underflow = tx_sync_reg_3[0] ^ tx_sync_reg_4[0]; + +always @(posedge tx_clk or posedge tx_rst) begin + if (tx_rst) begin + tx_sync_reg_1 <= 1'b0; + end else begin + tx_sync_reg_1 <= tx_sync_reg_1 ^ {tx_error_underflow_int}; + end +end + +always @(posedge logic_clk or posedge logic_rst) begin + if (logic_rst) begin + tx_sync_reg_2 <= 1'b0; + tx_sync_reg_3 <= 1'b0; + tx_sync_reg_4 <= 1'b0; + end else begin + tx_sync_reg_2 <= tx_sync_reg_1; + tx_sync_reg_3 <= tx_sync_reg_2; + tx_sync_reg_4 <= tx_sync_reg_3; + end +end + +wire rx_error_bad_frame_int; +wire rx_error_bad_fcs_int; + +reg [1:0] rx_sync_reg_1 = 2'd0; +reg [1:0] rx_sync_reg_2 = 2'd0; +reg [1:0] rx_sync_reg_3 = 2'd0; +reg [1:0] rx_sync_reg_4 = 2'd0; + +assign rx_error_bad_frame = rx_sync_reg_3[0] ^ rx_sync_reg_4[0]; +assign rx_error_bad_fcs = rx_sync_reg_3[1] ^ rx_sync_reg_4[1]; + +always @(posedge rx_clk or posedge rx_rst) begin + if (rx_rst) begin + rx_sync_reg_1 <= 2'd0; + end else begin + rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; + end +end + +always @(posedge logic_clk or posedge logic_rst) begin + if (logic_rst) begin + rx_sync_reg_2 <= 2'd0; + rx_sync_reg_3 <= 2'd0; + rx_sync_reg_4 <= 2'd0; + end else begin + rx_sync_reg_2 <= rx_sync_reg_1; + rx_sync_reg_3 <= rx_sync_reg_2; + rx_sync_reg_4 <= rx_sync_reg_3; + end +end + + // *** there are a bunch of missing pins + /* verilator lint_off PINMISSING */ +eth_mac_mii #( + .TARGET(TARGET), + .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), + .ENABLE_PADDING(ENABLE_PADDING), + .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH) +) +eth_mac_1g_mii_inst ( + .rst(rst), + .tx_clk(tx_clk), + .tx_rst(tx_rst), + .rx_clk(rx_clk), + .rx_rst(rx_rst), + .tx_axis_tdata(tx_fifo_axis_tdata), + .tx_axis_tvalid(tx_fifo_axis_tvalid), + .tx_axis_tready(tx_fifo_axis_tready), + .tx_axis_tlast(tx_fifo_axis_tlast), + .tx_axis_tuser(tx_fifo_axis_tuser), + .rx_axis_tdata(rx_fifo_axis_tdata), + .rx_axis_tvalid(rx_fifo_axis_tvalid), + .rx_axis_tlast(rx_fifo_axis_tlast), + .rx_axis_tuser(rx_fifo_axis_tuser), + .mii_rx_clk(mii_rx_clk), + .mii_rxd(mii_rxd), + .mii_rx_dv(mii_rx_dv), + .mii_rx_er(mii_rx_er), + .mii_tx_clk(mii_tx_clk), + .mii_txd(mii_txd), + .mii_tx_en(mii_tx_en), + .mii_tx_er(mii_tx_er), + .tx_error_underflow(tx_error_underflow_int), + .rx_error_bad_frame(rx_error_bad_frame_int), + .rx_error_bad_fcs(rx_error_bad_fcs_int), + .cfg_ifg(cfg_ifg), + .cfg_tx_enable(cfg_tx_enable), + .cfg_rx_enable(cfg_rx_enable) +); + +axis_async_fifo_adapter #( + .DEPTH(TX_FIFO_DEPTH), + .S_DATA_WIDTH(AXIS_DATA_WIDTH), + .S_KEEP_ENABLE(AXIS_KEEP_ENABLE), + .S_KEEP_WIDTH(AXIS_KEEP_WIDTH), + .M_DATA_WIDTH(8), + .M_KEEP_ENABLE(0), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(1), + .USER_WIDTH(1), + .RAM_PIPELINE(TX_FIFO_RAM_PIPELINE), + .FRAME_FIFO(TX_FRAME_FIFO), + .USER_BAD_FRAME_VALUE(1'b1), + .USER_BAD_FRAME_MASK(1'b1), + .DROP_OVERSIZE_FRAME(TX_DROP_OVERSIZE_FRAME), + .DROP_BAD_FRAME(TX_DROP_BAD_FRAME), + .DROP_WHEN_FULL(TX_DROP_WHEN_FULL) +) +tx_fifo ( + // AXI input + .s_clk(logic_clk), + .s_rst(logic_rst), + .s_axis_tdata(tx_axis_tdata), + .s_axis_tkeep(tx_axis_tkeep), + .s_axis_tvalid(tx_axis_tvalid), + .s_axis_tready(tx_axis_tready), + .s_axis_tlast(tx_axis_tlast), + .s_axis_tid(0), + .s_axis_tdest(0), + .s_axis_tuser(tx_axis_tuser), + // AXI output + .m_clk(tx_clk), + .m_rst(tx_rst), + .m_axis_tdata(tx_fifo_axis_tdata), + .m_axis_tkeep(), + .m_axis_tvalid(tx_fifo_axis_tvalid), + .m_axis_tready(tx_fifo_axis_tready), + .m_axis_tlast(tx_fifo_axis_tlast), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(tx_fifo_axis_tuser), + // Status + .s_status_overflow(tx_fifo_overflow), + .s_status_bad_frame(tx_fifo_bad_frame), + .s_status_good_frame(tx_fifo_good_frame), + .m_status_overflow(), + .m_status_bad_frame(), + .m_status_good_frame() +); + +axis_async_fifo_adapter #( + .DEPTH(RX_FIFO_DEPTH), + .S_DATA_WIDTH(8), + .S_KEEP_ENABLE(0), + .M_DATA_WIDTH(AXIS_DATA_WIDTH), + .M_KEEP_ENABLE(AXIS_KEEP_ENABLE), + .M_KEEP_WIDTH(AXIS_KEEP_WIDTH), + .ID_ENABLE(0), + .DEST_ENABLE(0), + .USER_ENABLE(1), + .USER_WIDTH(1), + .RAM_PIPELINE(RX_FIFO_RAM_PIPELINE), + .FRAME_FIFO(RX_FRAME_FIFO), + .USER_BAD_FRAME_VALUE(1'b1), + .USER_BAD_FRAME_MASK(1'b1), + .DROP_OVERSIZE_FRAME(RX_DROP_OVERSIZE_FRAME), + .DROP_BAD_FRAME(RX_DROP_BAD_FRAME), + .DROP_WHEN_FULL(RX_DROP_WHEN_FULL) +) +rx_fifo ( + // AXI input + .s_clk(rx_clk), + .s_rst(rx_rst), + .s_axis_tdata(rx_fifo_axis_tdata), + .s_axis_tkeep(0), + .s_axis_tvalid(rx_fifo_axis_tvalid), + .s_axis_tready(), + .s_axis_tlast(rx_fifo_axis_tlast), + .s_axis_tid(0), + .s_axis_tdest(0), + .s_axis_tuser(rx_fifo_axis_tuser), + // AXI output + .m_clk(logic_clk), + .m_rst(logic_rst), + .m_axis_tdata(rx_axis_tdata), + .m_axis_tkeep(rx_axis_tkeep), + .m_axis_tvalid(rx_axis_tvalid), + .m_axis_tready(rx_axis_tready), + .m_axis_tlast(rx_axis_tlast), + .m_axis_tid(), + .m_axis_tdest(), + .m_axis_tuser(rx_axis_tuser), + // Status + .s_status_overflow(), + .s_status_bad_frame(), + .s_status_good_frame(), + .m_status_overflow(rx_fifo_overflow), + .m_status_bad_frame(rx_fifo_bad_frame), + .m_status_good_frame(rx_fifo_good_frame) +); +/* verilator lint_on PINMISSING */ + +endmodule + +`resetall diff --git a/src/rvvi/lfsr.sv b/src/rvvi/lfsr.sv new file mode 100644 index 000000000..4b404fe94 --- /dev/null +++ b/src/rvvi/lfsr.sv @@ -0,0 +1,446 @@ +/* + +Copyright (c) 2016-2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * Parametrizable combinatorial parallel LFSR/CRC + */ +module lfsr # +( + // width of LFSR + parameter LFSR_WIDTH = 31, + // LFSR polynomial + parameter LFSR_POLY = 31'h10000001, + // LFSR configuration: "GALOIS", "FIBONACCI" + parameter LFSR_CONFIG = "FIBONACCI", + // LFSR feed forward enable + parameter LFSR_FEED_FORWARD = 0, + // bit-reverse input and output + parameter REVERSE = 0, + // width of data input + parameter DATA_WIDTH = 8, + // implementation style: "AUTO", "LOOP", "REDUCTION" + parameter STYLE = "AUTO" +) +( + input wire [DATA_WIDTH-1:0] data_in, + input wire [LFSR_WIDTH-1:0] state_in, + output wire [DATA_WIDTH-1:0] data_out, + output wire [LFSR_WIDTH-1:0] state_out +); + +/* + +Fully parametrizable combinatorial parallel LFSR/CRC module. Implements an unrolled LFSR +next state computation, shifting DATA_WIDTH bits per pass through the module. Input data +is XORed with LFSR feedback path, tie data_in to zero if this is not required. + +Works in two parts: statically computes a set of bit masks, then uses these bit masks to +select bits for XORing to compute the next state. + +Ports: + +data_in + +Data bits to be shifted through the LFSR (DATA_WIDTH bits) + +state_in + +LFSR/CRC current state input (LFSR_WIDTH bits) + +data_out + +Data bits shifted out of LFSR (DATA_WIDTH bits) + +state_out + +LFSR/CRC next state output (LFSR_WIDTH bits) + +Parameters: + +LFSR_WIDTH + +Specify width of LFSR/CRC register + +LFSR_POLY + +Specify the LFSR/CRC polynomial in hex format. For example, the polynomial + +x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + +would be represented as + +32'h04c11db7 + +Note that the largest term (x^32) is suppressed. This term is generated automatically based +on LFSR_WIDTH. + +LFSR_CONFIG + +Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used +for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators, +scramblers, and descrambers, while Galois is generally used for cyclic redundancy check +generators and checkers. + +Fibonacci style (example for 64b66b scrambler, 0x8000000001) + + DIN (LSB first) + | + V + (+)<---------------------------(+)<-----------------------------. + | ^ | + | .----. .----. .----. | .----. .----. .----. | + +->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--' + | '----' '----' '----' '----' '----' '----' + V + DOUT + +Galois style (example for CRC16, 0x8005) + + ,-------------------+-------------------------+----------(+)<-- DIN (MSB first) + | | | ^ + | .----. .----. V .----. .----. V .----. | + `->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT + '----' '----' '----' '----' '----' + +LFSR_FEED_FORWARD + +Generate feed forward instead of feed back LFSR. Enable this for PRBS checking and self- +synchronous descrambling. + +Fibonacci feed-forward style (example for 64b66b descrambler, 0x8000000001) + + DIN (LSB first) + | + | .----. .----. .----. .----. .----. .----. + +->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--. + | '----' '----' '----' | '----' '----' '----' | + | V | + (+)<---------------------------(+)------------------------------' + | + V + DOUT + +Galois feed-forward style + + ,-------------------+-------------------------+------------+--- DIN (MSB first) + | | | | + | .----. .----. V .----. .----. V .----. V + `->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |->(+)-> DOUT + '----' '----' '----' '----' '----' + +REVERSE + +Bit-reverse LFSR input and output. Shifts MSB first by default, set REVERSE for LSB first. + +DATA_WIDTH + +Specify width of input and output data bus. The module will perform one shift per input +data bit, so if the input data bus is not required tie data_in to zero and set DATA_WIDTH +to the required number of shifts per clock cycle. + +STYLE + +Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO" +is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate +directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate +and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog +reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction +operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in +Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing +problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO" +will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey +synthesis translate directives. + +Settings for common LFSR/CRC implementations: + +Name Configuration Length Polynomial Initial value Notes +CRC16-IBM Galois, bit-reverse 16 16'h8005 16'hffff +CRC16-CCITT Galois 16 16'h1021 16'h1d0f +CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output +CRC32C Galois, bit-reverse 32 32'h1edc6f41 32'hffffffff iSCSI, Intel CRC32 instruction; invert final output +PRBS6 Fibonacci 6 6'h21 any +PRBS7 Fibonacci 7 7'h41 any +PRBS9 Fibonacci 9 9'h021 any ITU V.52 +PRBS10 Fibonacci 10 10'h081 any ITU +PRBS11 Fibonacci 11 11'h201 any ITU O.152 +PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152 +PRBS17 Fibonacci 17 17'h04001 any +PRBS20 Fibonacci 20 20'h00009 any ITU V.57 +PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151 +PRBS29 Fibonacci, inverted 29 29'h08000001 any +PRBS31 Fibonacci, inverted 31 31'h10000001 any +64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet +128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3 + +*/ + +function [LFSR_WIDTH+DATA_WIDTH-1:0] lfsr_mask(input [31:0] index); + reg [LFSR_WIDTH-1:0] lfsr_mask_state[LFSR_WIDTH-1:0]; + reg [DATA_WIDTH-1:0] lfsr_mask_data[LFSR_WIDTH-1:0]; + reg [LFSR_WIDTH-1:0] output_mask_state[DATA_WIDTH-1:0]; + reg [DATA_WIDTH-1:0] output_mask_data[DATA_WIDTH-1:0]; + + reg [LFSR_WIDTH-1:0] state_val; + reg [DATA_WIDTH-1:0] data_val; + + reg [DATA_WIDTH-1:0] data_mask; + + integer i, j; + + begin + // init bit masks + for (i = 0; i < LFSR_WIDTH; i = i + 1) begin + lfsr_mask_state[i] = 0; + lfsr_mask_state[i][i] = 1'b1; + lfsr_mask_data[i] = 0; + end + for (i = 0; i < DATA_WIDTH; i = i + 1) begin + output_mask_state[i] = 0; + if (i < LFSR_WIDTH) begin + output_mask_state[i][i] = 1'b1; + end + output_mask_data[i] = 0; + end + + // simulate shift register + if (LFSR_CONFIG == "FIBONACCI") begin + // Fibonacci configuration + for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin + // determine shift in value + // current value in last FF, XOR with input data bit (MSB first) + state_val = lfsr_mask_state[LFSR_WIDTH-1]; + data_val = lfsr_mask_data[LFSR_WIDTH-1]; + data_val = data_val ^ data_mask; + + // add XOR inputs from correct indicies + for (j = 1; j < LFSR_WIDTH; j = j + 1) begin + if ((LFSR_POLY >> j) & 1) begin + state_val = lfsr_mask_state[j-1] ^ state_val; + data_val = lfsr_mask_data[j-1] ^ data_val; + end + end + + // shift + for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin + lfsr_mask_state[j] = lfsr_mask_state[j-1]; + lfsr_mask_data[j] = lfsr_mask_data[j-1]; + end + for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin + output_mask_state[j] = output_mask_state[j-1]; + output_mask_data[j] = output_mask_data[j-1]; + end + output_mask_state[0] = state_val; + output_mask_data[0] = data_val; + if (LFSR_FEED_FORWARD) begin + // only shift in new input data + state_val = {LFSR_WIDTH{1'b0}}; + data_val = data_mask; + end + lfsr_mask_state[0] = state_val; + lfsr_mask_data[0] = data_val; + end + end else if (LFSR_CONFIG == "GALOIS") begin + // Galois configuration + for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin + // determine shift in value + // current value in last FF, XOR with input data bit (MSB first) + state_val = lfsr_mask_state[LFSR_WIDTH-1]; + data_val = lfsr_mask_data[LFSR_WIDTH-1]; + data_val = data_val ^ data_mask; + + // shift + for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin + lfsr_mask_state[j] = lfsr_mask_state[j-1]; + lfsr_mask_data[j] = lfsr_mask_data[j-1]; + end + for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin + output_mask_state[j] = output_mask_state[j-1]; + output_mask_data[j] = output_mask_data[j-1]; + end + output_mask_state[0] = state_val; + output_mask_data[0] = data_val; + if (LFSR_FEED_FORWARD) begin + // only shift in new input data + state_val = {LFSR_WIDTH{1'b0}}; + data_val = data_mask; + end + lfsr_mask_state[0] = state_val; + lfsr_mask_data[0] = data_val; + + // add XOR inputs at correct indicies + for (j = 1; j < LFSR_WIDTH; j = j + 1) begin + if ((LFSR_POLY >> j) & 1) begin + lfsr_mask_state[j] = lfsr_mask_state[j] ^ state_val; + lfsr_mask_data[j] = lfsr_mask_data[j] ^ data_val; + end + end + end + end else begin + $error("Error: unknown configuration setting!"); + $finish; + end + + // reverse bits if selected + if (REVERSE) begin + if (index < LFSR_WIDTH) begin + state_val = 0; + for (i = 0; i < LFSR_WIDTH; i = i + 1) begin + state_val[i] = lfsr_mask_state[LFSR_WIDTH-index-1][LFSR_WIDTH-i-1]; + end + + data_val = 0; + for (i = 0; i < DATA_WIDTH; i = i + 1) begin + data_val[i] = lfsr_mask_data[LFSR_WIDTH-index-1][DATA_WIDTH-i-1]; + end + end else begin + state_val = 0; + for (i = 0; i < LFSR_WIDTH; i = i + 1) begin + state_val[i] = output_mask_state[DATA_WIDTH-(index-LFSR_WIDTH)-1][LFSR_WIDTH-i-1]; + end + + data_val = 0; + for (i = 0; i < DATA_WIDTH; i = i + 1) begin + data_val[i] = output_mask_data[DATA_WIDTH-(index-LFSR_WIDTH)-1][DATA_WIDTH-i-1]; + end + end + end else begin + if (index < LFSR_WIDTH) begin + state_val = lfsr_mask_state[index]; + data_val = lfsr_mask_data[index]; + end else begin + state_val = output_mask_state[index-LFSR_WIDTH]; + data_val = output_mask_data[index-LFSR_WIDTH]; + end + end + lfsr_mask = {data_val, state_val}; + end +endfunction + +// synthesis translate_off +`define SIMULATION +// synthesis translate_on + +`ifdef SIMULATION +// "AUTO" style is "REDUCTION" for faster simulation +parameter STYLE_INT = (STYLE == "AUTO") ? "REDUCTION" : STYLE; +`else +// "AUTO" style is "LOOP" for better synthesis result +parameter STYLE_INT = (STYLE == "AUTO") ? "LOOP" : STYLE; +`endif + +genvar n; + +generate + +if (STYLE_INT == "REDUCTION") begin + + // use Verilog reduction operator + // fast in iverilog + // significantly larger than generated code with ISE (inferred wide XORs may be tripping up optimizer) + // slightly smaller than generated code with Quartus + // --> better for simulation + + for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state + wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n); + assign state_out[n] = ^({data_in, state_in} & mask); + end + for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data + wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH); + assign data_out[n] = ^({data_in, state_in} & mask); + end + +end else if (STYLE_INT == "LOOP") begin + + // use nested loops + // very slow in iverilog + // slightly smaller than generated code with ISE + // same size as generated code with Quartus + // --> better for synthesis + + for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state + wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n); + + reg state_reg; + + assign state_out[n] = state_reg; + + integer i; + + always @* begin + state_reg = 1'b0; + for (i = 0; i < LFSR_WIDTH; i = i + 1) begin + if (mask[i]) begin + state_reg = state_reg ^ state_in[i]; + end + end + for (i = 0; i < DATA_WIDTH; i = i + 1) begin + if (mask[i+LFSR_WIDTH]) begin + state_reg = state_reg ^ data_in[i]; + end + end + end + end + for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data + wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH); + + reg data_reg; + + assign data_out[n] = data_reg; + + integer i; + + always @* begin + data_reg = 1'b0; + for (i = 0; i < LFSR_WIDTH; i = i + 1) begin + if (mask[i]) begin + data_reg = data_reg ^ state_in[i]; + end + end + for (i = 0; i < DATA_WIDTH; i = i + 1) begin + if (mask[i+LFSR_WIDTH]) begin + data_reg = data_reg ^ data_in[i]; + end + end + end + end + +end else begin + + initial begin + $error("Error: unknown style setting!"); + $finish; + end + +end + +endgenerate + +endmodule + +`resetall diff --git a/src/rvvi/mac_ctrl_rx.sv b/src/rvvi/mac_ctrl_rx.sv new file mode 100644 index 000000000..f7171887b --- /dev/null +++ b/src/rvvi/mac_ctrl_rx.sv @@ -0,0 +1,447 @@ +/* + +Copyright (c) 2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * MAC control receive + */ +module mac_ctrl_rx # +( + parameter DATA_WIDTH = 8, + parameter KEEP_ENABLE = DATA_WIDTH>8, + parameter KEEP_WIDTH = DATA_WIDTH/8, + parameter ID_ENABLE = 0, + parameter ID_WIDTH = 8, + parameter DEST_ENABLE = 0, + parameter DEST_WIDTH = 8, + parameter USER_ENABLE = 1, + parameter USER_WIDTH = 1, + parameter USE_READY = 0, + parameter MCF_PARAMS_SIZE = 18 +) +( + input wire clk, + input wire rst, + + /* + * AXI stream input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire [KEEP_WIDTH-1:0] s_axis_tkeep, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire [ID_WIDTH-1:0] s_axis_tid, + input wire [DEST_WIDTH-1:0] s_axis_tdest, + input wire [USER_WIDTH-1:0] s_axis_tuser, + + /* + * AXI stream output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire [KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire [ID_WIDTH-1:0] m_axis_tid, + output wire [DEST_WIDTH-1:0] m_axis_tdest, + output wire [USER_WIDTH-1:0] m_axis_tuser, + + /* + * MAC control frame interface + */ + output wire mcf_valid, + output wire [47:0] mcf_eth_dst, + output wire [47:0] mcf_eth_src, + output wire [15:0] mcf_eth_type, + output wire [15:0] mcf_opcode, + output wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, + output wire [ID_WIDTH-1:0] mcf_id, + output wire [DEST_WIDTH-1:0] mcf_dest, + output wire [USER_WIDTH-1:0] mcf_user, + + /* + * Configuration + */ + input wire [47:0] cfg_mcf_rx_eth_dst_mcast, + input wire cfg_mcf_rx_check_eth_dst_mcast, + input wire [47:0] cfg_mcf_rx_eth_dst_ucast, + input wire cfg_mcf_rx_check_eth_dst_ucast, + input wire [47:0] cfg_mcf_rx_eth_src, + input wire cfg_mcf_rx_check_eth_src, + input wire [15:0] cfg_mcf_rx_eth_type, + input wire [15:0] cfg_mcf_rx_opcode_lfc, + input wire cfg_mcf_rx_check_opcode_lfc, + input wire [15:0] cfg_mcf_rx_opcode_pfc, + input wire cfg_mcf_rx_check_opcode_pfc, + input wire cfg_mcf_rx_forward, + input wire cfg_mcf_rx_enable, + + /* + * Status + */ + output wire stat_rx_mcf +); + +parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; + +parameter HDR_SIZE = 60; + +parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; + +parameter PTR_WIDTH = $clog2(CYCLE_COUNT); + +parameter OFFSET = HDR_SIZE % BYTE_LANES; + +// check configuration +initial begin + if (BYTE_LANES * 8 != DATA_WIDTH) begin + $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); + $finish; + end + + if (MCF_PARAMS_SIZE > 44) begin + $error("Error: Maximum MCF_PARAMS_SIZE is 44 bytes (instance %m)"); + $finish; + end +end + +/* + +MAC control frame + + Field Length + Destination MAC address 6 octets [01:80:C2:00:00:01] + Source MAC address 6 octets + Ethertype 2 octets [0x8808] + Opcode 2 octets + Parameters 0-44 octets + +This module manages the reception of MAC control frames. Incoming frames are +checked based on the ethertype and (optionally) MAC addresses. Matching control +frames are marked by setting tuser[0] on the data output and forwarded through +a separate interface for processing. + +*/ + +reg read_mcf_reg = 1'b1, read_mcf_next; +reg mcf_frame_reg = 1'b0, mcf_frame_next; +reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; + +reg s_axis_tready_reg = 1'b0, s_axis_tready_next; + +// internal datapath +reg [DATA_WIDTH-1:0] m_axis_tdata_int; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; +reg m_axis_tvalid_int; +reg m_axis_tready_int_reg = 1'b0; +reg m_axis_tlast_int; +reg [ID_WIDTH-1:0] m_axis_tid_int; +reg [DEST_WIDTH-1:0] m_axis_tdest_int; +reg [USER_WIDTH-1:0] m_axis_tuser_int; +wire m_axis_tready_int_early; + +reg mcf_valid_reg = 0, mcf_valid_next; +reg [47:0] mcf_eth_dst_reg = 0, mcf_eth_dst_next; +reg [47:0] mcf_eth_src_reg = 0, mcf_eth_src_next; +reg [15:0] mcf_eth_type_reg = 0, mcf_eth_type_next; +reg [15:0] mcf_opcode_reg = 0, mcf_opcode_next; +reg [MCF_PARAMS_SIZE*8-1:0] mcf_params_reg = 0, mcf_params_next; +reg [ID_WIDTH-1:0] mcf_id_reg = 0, mcf_id_next; +reg [DEST_WIDTH-1:0] mcf_dest_reg = 0, mcf_dest_next; +reg [USER_WIDTH-1:0] mcf_user_reg = 0, mcf_user_next; + +reg stat_rx_mcf_reg = 1'b0, stat_rx_mcf_next; + +assign s_axis_tready = s_axis_tready_reg; + +assign mcf_valid = mcf_valid_reg; +assign mcf_eth_dst = mcf_eth_dst_reg; +assign mcf_eth_src = mcf_eth_src_reg; +assign mcf_eth_type = mcf_eth_type_reg; +assign mcf_opcode = mcf_opcode_reg; +assign mcf_params = mcf_params_reg; +assign mcf_id = mcf_id_reg; +assign mcf_dest = mcf_dest_reg; +assign mcf_user = mcf_user_reg; + +assign stat_rx_mcf = stat_rx_mcf_reg; + +wire mcf_eth_dst_mcast_match = mcf_eth_dst_next == cfg_mcf_rx_eth_dst_mcast; +wire mcf_eth_dst_ucast_match = mcf_eth_dst_next == cfg_mcf_rx_eth_dst_ucast; +wire mcf_eth_src_match = mcf_eth_src_next == cfg_mcf_rx_eth_src; +wire mcf_eth_type_match = mcf_eth_type_next == cfg_mcf_rx_eth_type; +wire mcf_opcode_lfc_match = mcf_opcode_next == cfg_mcf_rx_opcode_lfc; +wire mcf_opcode_pfc_match = mcf_opcode_next == cfg_mcf_rx_opcode_pfc; + +wire mcf_eth_dst_match = ((mcf_eth_dst_mcast_match && cfg_mcf_rx_check_eth_dst_mcast) || + (mcf_eth_dst_ucast_match && cfg_mcf_rx_check_eth_dst_ucast) || + (!cfg_mcf_rx_check_eth_dst_mcast && !cfg_mcf_rx_check_eth_dst_ucast)); + +wire mcf_opcode_match = ((mcf_opcode_lfc_match && cfg_mcf_rx_check_opcode_lfc) || + (mcf_opcode_pfc_match && cfg_mcf_rx_check_opcode_pfc) || + (!cfg_mcf_rx_check_opcode_lfc && !cfg_mcf_rx_check_opcode_pfc)); + +wire mcf_match = (mcf_eth_dst_match && + (mcf_eth_src_match || !cfg_mcf_rx_check_eth_src) && + mcf_eth_type_match && mcf_opcode_match); + +integer k; + +always @* begin + read_mcf_next = read_mcf_reg; + mcf_frame_next = mcf_frame_reg; + ptr_next = ptr_reg; + + // pass through data + m_axis_tdata_int = s_axis_tdata; + m_axis_tkeep_int = s_axis_tkeep; + m_axis_tvalid_int = s_axis_tvalid; + m_axis_tlast_int = s_axis_tlast; + m_axis_tid_int = s_axis_tid; + m_axis_tdest_int = s_axis_tdest; + m_axis_tuser_int = s_axis_tuser; + + s_axis_tready_next = m_axis_tready_int_early || !USE_READY; + + mcf_valid_next = 1'b0; + mcf_eth_dst_next = mcf_eth_dst_reg; + mcf_eth_src_next = mcf_eth_src_reg; + mcf_eth_type_next = mcf_eth_type_reg; + mcf_opcode_next = mcf_opcode_reg; + mcf_params_next = mcf_params_reg; + mcf_id_next = mcf_id_reg; + mcf_dest_next = mcf_dest_reg; + mcf_user_next = mcf_user_reg; + + stat_rx_mcf_next = 1'b0; + + if ((s_axis_tready || !USE_READY) && s_axis_tvalid) begin + if (read_mcf_reg) begin + ptr_next = ptr_reg + 1; + + mcf_id_next = s_axis_tid; + mcf_dest_next = s_axis_tdest; + mcf_user_next = s_axis_tuser; + + `define _HEADER_FIELD_(offset, field) \ + if (ptr_reg == offset/BYTE_LANES) begin \ + field = s_axis_tdata[(offset%BYTE_LANES)*8 +: 8]; \ + end + + `_HEADER_FIELD_(0, mcf_eth_dst_next[5*8 +: 8]) + `_HEADER_FIELD_(1, mcf_eth_dst_next[4*8 +: 8]) + `_HEADER_FIELD_(2, mcf_eth_dst_next[3*8 +: 8]) + `_HEADER_FIELD_(3, mcf_eth_dst_next[2*8 +: 8]) + `_HEADER_FIELD_(4, mcf_eth_dst_next[1*8 +: 8]) + `_HEADER_FIELD_(5, mcf_eth_dst_next[0*8 +: 8]) + `_HEADER_FIELD_(6, mcf_eth_src_next[5*8 +: 8]) + `_HEADER_FIELD_(7, mcf_eth_src_next[4*8 +: 8]) + `_HEADER_FIELD_(8, mcf_eth_src_next[3*8 +: 8]) + `_HEADER_FIELD_(9, mcf_eth_src_next[2*8 +: 8]) + `_HEADER_FIELD_(10, mcf_eth_src_next[1*8 +: 8]) + `_HEADER_FIELD_(11, mcf_eth_src_next[0*8 +: 8]) + `_HEADER_FIELD_(12, mcf_eth_type_next[1*8 +: 8]) + `_HEADER_FIELD_(13, mcf_eth_type_next[0*8 +: 8]) + `_HEADER_FIELD_(14, mcf_opcode_next[1*8 +: 8]) + `_HEADER_FIELD_(15, mcf_opcode_next[0*8 +: 8]) + + if (ptr_reg == 0/BYTE_LANES) begin + // ensure params field gets cleared + mcf_params_next = 0; + end + + for (k = 0; k < MCF_PARAMS_SIZE; k = k + 1) begin + if (ptr_reg == (16+k)/BYTE_LANES) begin + mcf_params_next[k*8 +: 8] = s_axis_tdata[((16+k)%BYTE_LANES)*8 +: 8]; + end + end + + if (ptr_reg == 15/BYTE_LANES && (!KEEP_ENABLE || s_axis_tkeep[13%BYTE_LANES])) begin + // record match at end of opcode field + mcf_frame_next = mcf_match && cfg_mcf_rx_enable; + end + + if (ptr_reg == (HDR_SIZE-1)/BYTE_LANES) begin + read_mcf_next = 1'b0; + end + + `undef _HEADER_FIELD_ + end + + if (s_axis_tlast) begin + if (s_axis_tuser[0]) begin + // frame marked invalid + end else if (mcf_frame_next) begin + if (!cfg_mcf_rx_forward) begin + // mark frame invalid + m_axis_tuser_int[0] = 1'b1; + end + // transfer out MAC control frame + mcf_valid_next = 1'b1; + stat_rx_mcf_next = 1'b1; + end + + read_mcf_next = 1'b1; + mcf_frame_next = 1'b0; + ptr_next = 0; + end + end +end + +always @(posedge clk) begin + read_mcf_reg <= read_mcf_next; + mcf_frame_reg <= mcf_frame_next; + ptr_reg <= ptr_next; + + s_axis_tready_reg <= s_axis_tready_next; + + mcf_valid_reg <= mcf_valid_next; + mcf_eth_dst_reg <= mcf_eth_dst_next; + mcf_eth_src_reg <= mcf_eth_src_next; + mcf_eth_type_reg <= mcf_eth_type_next; + mcf_opcode_reg <= mcf_opcode_next; + mcf_params_reg <= mcf_params_next; + mcf_id_reg <= mcf_id_next; + mcf_dest_reg <= mcf_dest_next; + mcf_user_reg <= mcf_user_next; + + stat_rx_mcf_reg <= stat_rx_mcf_next; + + if (rst) begin + read_mcf_reg <= 1'b1; + mcf_frame_reg <= 1'b0; + ptr_reg <= 0; + s_axis_tready_reg <= 1'b0; + mcf_valid_reg <= 1'b0; + stat_rx_mcf_reg <= 1'b0; + end +end + +// output datapath logic +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; +reg m_axis_tlast_reg = 1'b0; +reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; +reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; +reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + +reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; +reg temp_m_axis_tlast_reg = 1'b0; +reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; +reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; +reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; +assign m_axis_tvalid = m_axis_tvalid_reg; +assign m_axis_tlast = m_axis_tlast_reg; +assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; +assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; +assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign m_axis_tready_int_early = m_axis_tready || !USE_READY || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + m_axis_tvalid_next = m_axis_tvalid_reg; + temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (m_axis_tready_int_reg) begin + // input is ready + if (m_axis_tready || !USE_READY || !m_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (m_axis_tready || !USE_READY) begin + // input is not ready, but output is ready + m_axis_tvalid_next = temp_m_axis_tvalid_reg; + temp_m_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + m_axis_tvalid_reg <= m_axis_tvalid_next; + m_axis_tready_int_reg <= m_axis_tready_int_early; + temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; + + // datapath + if (store_axis_int_to_output) begin + m_axis_tdata_reg <= m_axis_tdata_int; + m_axis_tkeep_reg <= m_axis_tkeep_int; + m_axis_tlast_reg <= m_axis_tlast_int; + m_axis_tid_reg <= m_axis_tid_int; + m_axis_tdest_reg <= m_axis_tdest_int; + m_axis_tuser_reg <= m_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + m_axis_tdata_reg <= temp_m_axis_tdata_reg; + m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; + m_axis_tlast_reg <= temp_m_axis_tlast_reg; + m_axis_tid_reg <= temp_m_axis_tid_reg; + m_axis_tdest_reg <= temp_m_axis_tdest_reg; + m_axis_tuser_reg <= temp_m_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_m_axis_tdata_reg <= m_axis_tdata_int; + temp_m_axis_tkeep_reg <= m_axis_tkeep_int; + temp_m_axis_tlast_reg <= m_axis_tlast_int; + temp_m_axis_tid_reg <= m_axis_tid_int; + temp_m_axis_tdest_reg <= m_axis_tdest_int; + temp_m_axis_tuser_reg <= m_axis_tuser_int; + end + + if (rst) begin + m_axis_tvalid_reg <= 1'b0; + m_axis_tready_int_reg <= 1'b0; + temp_m_axis_tvalid_reg <= 1'b0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/mac_ctrl_tx.sv b/src/rvvi/mac_ctrl_tx.sv new file mode 100644 index 000000000..3d321fd64 --- /dev/null +++ b/src/rvvi/mac_ctrl_tx.sv @@ -0,0 +1,420 @@ +/* + +Copyright (c) 2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * MAC control transmit + */ +module mac_ctrl_tx # +( + parameter DATA_WIDTH = 8, + parameter KEEP_ENABLE = DATA_WIDTH>8, + parameter KEEP_WIDTH = DATA_WIDTH/8, + parameter ID_ENABLE = 0, + parameter ID_WIDTH = 8, + parameter DEST_ENABLE = 0, + parameter DEST_WIDTH = 8, + parameter USER_ENABLE = 1, + parameter USER_WIDTH = 1, + parameter MCF_PARAMS_SIZE = 18 +) +( + input wire clk, + input wire rst, + + /* + * AXI stream input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire [KEEP_WIDTH-1:0] s_axis_tkeep, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire [ID_WIDTH-1:0] s_axis_tid, + input wire [DEST_WIDTH-1:0] s_axis_tdest, + input wire [USER_WIDTH-1:0] s_axis_tuser, + + /* + * AXI stream output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire [KEEP_WIDTH-1:0] m_axis_tkeep, + output wire m_axis_tvalid, + input wire m_axis_tready, + output wire m_axis_tlast, + output wire [ID_WIDTH-1:0] m_axis_tid, + output wire [DEST_WIDTH-1:0] m_axis_tdest, + output wire [USER_WIDTH-1:0] m_axis_tuser, + + /* + * MAC control frame interface + */ + input wire mcf_valid, + output wire mcf_ready, + input wire [47:0] mcf_eth_dst, + input wire [47:0] mcf_eth_src, + input wire [15:0] mcf_eth_type, + input wire [15:0] mcf_opcode, + input wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, + input wire [ID_WIDTH-1:0] mcf_id, + input wire [DEST_WIDTH-1:0] mcf_dest, + input wire [USER_WIDTH-1:0] mcf_user, + + /* + * Pause interface + */ + input wire tx_pause_req, + output wire tx_pause_ack, + + /* + * Status + */ + output wire stat_tx_mcf +); + +parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; + +parameter HDR_SIZE = 60; + +parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; + +parameter PTR_WIDTH = $clog2(CYCLE_COUNT); + +parameter OFFSET = HDR_SIZE % BYTE_LANES; + +// check configuration +initial begin + if (BYTE_LANES * 8 != DATA_WIDTH) begin + $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); + $finish; + end + + if (MCF_PARAMS_SIZE > 44) begin + $error("Error: Maximum MCF_PARAMS_SIZE is 44 bytes (instance %m)"); + $finish; + end +end + +/* + +MAC control frame + + Field Length + Destination MAC address 6 octets [01:80:C2:00:00:01] + Source MAC address 6 octets + Ethertype 2 octets [0x8808] + Opcode 2 octets + Parameters 0-44 octets + +This module manages the transmission of MAC control frames. Control frames +are accepted in parallel, serialized, and merged at a higher priority with +data traffic. + +*/ + +reg send_data_reg = 1'b0, send_data_next; +reg send_mcf_reg = 1'b0, send_mcf_next; +reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; + +reg s_axis_tready_reg = 1'b0, s_axis_tready_next; +reg mcf_ready_reg = 1'b0, mcf_ready_next; +reg tx_pause_ack_reg = 1'b0, tx_pause_ack_next; +reg stat_tx_mcf_reg = 1'b0, stat_tx_mcf_next; + +// internal datapath +reg [DATA_WIDTH-1:0] m_axis_tdata_int; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; +reg m_axis_tvalid_int; +reg m_axis_tready_int_reg = 1'b0; +reg m_axis_tlast_int; +reg [ID_WIDTH-1:0] m_axis_tid_int; +reg [DEST_WIDTH-1:0] m_axis_tdest_int; +reg [USER_WIDTH-1:0] m_axis_tuser_int; +wire m_axis_tready_int_early; + +assign s_axis_tready = s_axis_tready_reg; +assign mcf_ready = mcf_ready_reg; +assign tx_pause_ack = tx_pause_ack_reg; +assign stat_tx_mcf = stat_tx_mcf_reg; + +integer k; + +always @* begin + send_data_next = send_data_reg; + send_mcf_next = send_mcf_reg; + ptr_next = ptr_reg; + + s_axis_tready_next = 1'b0; + mcf_ready_next = 1'b0; + tx_pause_ack_next = tx_pause_ack_reg; + stat_tx_mcf_next = 1'b0; + + m_axis_tdata_int = 0; + m_axis_tkeep_int = 0; + m_axis_tvalid_int = 1'b0; + m_axis_tlast_int = 1'b0; + m_axis_tid_int = 0; + m_axis_tdest_int = 0; + m_axis_tuser_int = 0; + + if (!send_data_reg && !send_mcf_reg) begin + m_axis_tdata_int = s_axis_tdata; + m_axis_tkeep_int = s_axis_tkeep; + m_axis_tvalid_int = 1'b0; + m_axis_tlast_int = s_axis_tlast; + m_axis_tid_int = s_axis_tid; + m_axis_tdest_int = s_axis_tdest; + m_axis_tuser_int = s_axis_tuser; + s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; + tx_pause_ack_next = tx_pause_req; + if (s_axis_tvalid && s_axis_tready) begin + s_axis_tready_next = m_axis_tready_int_early; + tx_pause_ack_next = 1'b0; + m_axis_tvalid_int = 1'b1; + if (s_axis_tlast) begin + s_axis_tready_next = m_axis_tready_int_early && !mcf_valid && !mcf_ready; + send_data_next = 1'b0; + end else begin + send_data_next = 1'b1; + end + end else if (mcf_valid) begin + s_axis_tready_next = 1'b0; + ptr_next = 0; + send_mcf_next = 1'b1; + mcf_ready_next = (CYCLE_COUNT == 1) && m_axis_tready_int_early; + end + end + + if (send_data_reg) begin + m_axis_tdata_int = s_axis_tdata; + m_axis_tkeep_int = s_axis_tkeep; + m_axis_tvalid_int = 1'b0; + m_axis_tlast_int = s_axis_tlast; + m_axis_tid_int = s_axis_tid; + m_axis_tdest_int = s_axis_tdest; + m_axis_tuser_int = s_axis_tuser; + s_axis_tready_next = m_axis_tready_int_early; + if (s_axis_tvalid && s_axis_tready) begin + m_axis_tvalid_int = 1'b1; + if (s_axis_tlast) begin + s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; + send_data_next = 1'b0; + if (mcf_valid) begin + s_axis_tready_next = 1'b0; + ptr_next = 0; + send_mcf_next = 1'b1; + mcf_ready_next = (CYCLE_COUNT == 1) && m_axis_tready_int_early; + end + end else begin + send_data_next = 1'b1; + end + end + end + + if (send_mcf_reg) begin + mcf_ready_next = (CYCLE_COUNT == 1 || ptr_reg == CYCLE_COUNT-1) && m_axis_tready_int_early; + if (m_axis_tready_int_reg) begin + ptr_next = ptr_reg + 1; + + m_axis_tvalid_int = 1'b1; + m_axis_tid_int = mcf_id; + m_axis_tdest_int = mcf_dest; + m_axis_tuser_int = mcf_user; + + `define _HEADER_FIELD_(offset, field) \ + if (ptr_reg == offset/BYTE_LANES) begin \ + m_axis_tdata_int[(offset%BYTE_LANES)*8 +: 8] = field; \ + m_axis_tkeep_int[offset%BYTE_LANES] = 1'b1; \ + end + + `_HEADER_FIELD_(0, mcf_eth_dst[5*8 +: 8]) + `_HEADER_FIELD_(1, mcf_eth_dst[4*8 +: 8]) + `_HEADER_FIELD_(2, mcf_eth_dst[3*8 +: 8]) + `_HEADER_FIELD_(3, mcf_eth_dst[2*8 +: 8]) + `_HEADER_FIELD_(4, mcf_eth_dst[1*8 +: 8]) + `_HEADER_FIELD_(5, mcf_eth_dst[0*8 +: 8]) + `_HEADER_FIELD_(6, mcf_eth_src[5*8 +: 8]) + `_HEADER_FIELD_(7, mcf_eth_src[4*8 +: 8]) + `_HEADER_FIELD_(8, mcf_eth_src[3*8 +: 8]) + `_HEADER_FIELD_(9, mcf_eth_src[2*8 +: 8]) + `_HEADER_FIELD_(10, mcf_eth_src[1*8 +: 8]) + `_HEADER_FIELD_(11, mcf_eth_src[0*8 +: 8]) + `_HEADER_FIELD_(12, mcf_eth_type[1*8 +: 8]) + `_HEADER_FIELD_(13, mcf_eth_type[0*8 +: 8]) + `_HEADER_FIELD_(14, mcf_opcode[1*8 +: 8]) + `_HEADER_FIELD_(15, mcf_opcode[0*8 +: 8]) + + for (k = 0; k < HDR_SIZE-16; k = k + 1) begin + if (ptr_reg == (16+k)/BYTE_LANES) begin + if (k < MCF_PARAMS_SIZE) begin + m_axis_tdata_int[((16+k)%BYTE_LANES)*8 +: 8] = mcf_params[k*8 +: 8]; + end else begin + m_axis_tdata_int[((16+k)%BYTE_LANES)*8 +: 8] = 0; + end + m_axis_tkeep_int[(16+k)%BYTE_LANES] = 1'b1; + end + end + + if (ptr_reg == (HDR_SIZE-1)/BYTE_LANES) begin + s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; + mcf_ready_next = 1'b0; + m_axis_tlast_int = 1'b1; + send_mcf_next = 1'b0; + stat_tx_mcf_next = 1'b1; + end else begin + mcf_ready_next = (ptr_next == CYCLE_COUNT-1) && m_axis_tready_int_early; + end + + `undef _HEADER_FIELD_ + end + end +end + +always @(posedge clk) begin + send_data_reg <= send_data_next; + send_mcf_reg <= send_mcf_next; + ptr_reg <= ptr_next; + + s_axis_tready_reg <= s_axis_tready_next; + mcf_ready_reg <= mcf_ready_next; + tx_pause_ack_reg <= tx_pause_ack_next; + stat_tx_mcf_reg <= stat_tx_mcf_next; + + if (rst) begin + send_data_reg <= 1'b0; + send_mcf_reg <= 1'b0; + ptr_reg <= 0; + s_axis_tready_reg <= 1'b0; + mcf_ready_reg <= 1'b0; + tx_pause_ack_reg <= 1'b0; + stat_tx_mcf_reg <= 1'b0; + end +end + +// output datapath logic +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; +reg m_axis_tlast_reg = 1'b0; +reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; +reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; +reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + +reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; +reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; +reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; +reg temp_m_axis_tlast_reg = 1'b0; +reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; +reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; +reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; + +// datapath control +reg store_axis_int_to_output; +reg store_axis_int_to_temp; +reg store_axis_temp_to_output; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; +assign m_axis_tvalid = m_axis_tvalid_reg; +assign m_axis_tlast = m_axis_tlast_reg; +assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; +assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; +assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; + +// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) +assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int)); + +always @* begin + // transfer sink ready state to source + m_axis_tvalid_next = m_axis_tvalid_reg; + temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; + + store_axis_int_to_output = 1'b0; + store_axis_int_to_temp = 1'b0; + store_axis_temp_to_output = 1'b0; + + if (m_axis_tready_int_reg) begin + // input is ready + if (m_axis_tready || !m_axis_tvalid_reg) begin + // output is ready or currently not valid, transfer data to output + m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_output = 1'b1; + end else begin + // output is not ready, store input in temp + temp_m_axis_tvalid_next = m_axis_tvalid_int; + store_axis_int_to_temp = 1'b1; + end + end else if (m_axis_tready) begin + // input is not ready, but output is ready + m_axis_tvalid_next = temp_m_axis_tvalid_reg; + temp_m_axis_tvalid_next = 1'b0; + store_axis_temp_to_output = 1'b1; + end +end + +always @(posedge clk) begin + m_axis_tvalid_reg <= m_axis_tvalid_next; + m_axis_tready_int_reg <= m_axis_tready_int_early; + temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; + + // datapath + if (store_axis_int_to_output) begin + m_axis_tdata_reg <= m_axis_tdata_int; + m_axis_tkeep_reg <= m_axis_tkeep_int; + m_axis_tlast_reg <= m_axis_tlast_int; + m_axis_tid_reg <= m_axis_tid_int; + m_axis_tdest_reg <= m_axis_tdest_int; + m_axis_tuser_reg <= m_axis_tuser_int; + end else if (store_axis_temp_to_output) begin + m_axis_tdata_reg <= temp_m_axis_tdata_reg; + m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; + m_axis_tlast_reg <= temp_m_axis_tlast_reg; + m_axis_tid_reg <= temp_m_axis_tid_reg; + m_axis_tdest_reg <= temp_m_axis_tdest_reg; + m_axis_tuser_reg <= temp_m_axis_tuser_reg; + end + + if (store_axis_int_to_temp) begin + temp_m_axis_tdata_reg <= m_axis_tdata_int; + temp_m_axis_tkeep_reg <= m_axis_tkeep_int; + temp_m_axis_tlast_reg <= m_axis_tlast_int; + temp_m_axis_tid_reg <= m_axis_tid_int; + temp_m_axis_tdest_reg <= m_axis_tdest_int; + temp_m_axis_tuser_reg <= m_axis_tuser_int; + end + + if (rst) begin + m_axis_tvalid_reg <= 1'b0; + m_axis_tready_int_reg <= 1'b0; + temp_m_axis_tvalid_reg <= 1'b0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/mac_pause_ctrl_rx.sv b/src/rvvi/mac_pause_ctrl_rx.sv new file mode 100644 index 000000000..e95c07bf9 --- /dev/null +++ b/src/rvvi/mac_pause_ctrl_rx.sv @@ -0,0 +1,220 @@ +/* + +Copyright (c) 2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * PFC and pause frame receive handling + */ +module mac_pause_ctrl_rx # +( + parameter MCF_PARAMS_SIZE = 18, + parameter PFC_ENABLE = 1 +) +( + input wire clk, + input wire rst, + + /* + * MAC control frame interface + */ + input wire mcf_valid, + input wire [47:0] mcf_eth_dst, + input wire [47:0] mcf_eth_src, + input wire [15:0] mcf_eth_type, + input wire [15:0] mcf_opcode, + input wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, + + /* + * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) + */ + input wire rx_lfc_en, + output wire rx_lfc_req, + input wire rx_lfc_ack, + + /* + * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) + */ + input wire [7:0] rx_pfc_en, + output wire [7:0] rx_pfc_req, + input wire [7:0] rx_pfc_ack, + + /* + * Configuration + */ + input wire [15:0] cfg_rx_lfc_opcode, + input wire cfg_rx_lfc_en, + input wire [15:0] cfg_rx_pfc_opcode, + input wire cfg_rx_pfc_en, + input wire [9:0] cfg_quanta_step, + input wire cfg_quanta_clk_en, + + /* + * Status + */ + output wire stat_rx_lfc_pkt, + output wire stat_rx_lfc_xon, + output wire stat_rx_lfc_xoff, + output wire stat_rx_lfc_paused, + output wire stat_rx_pfc_pkt, + output wire [7:0] stat_rx_pfc_xon, + output wire [7:0] stat_rx_pfc_xoff, + output wire [7:0] stat_rx_pfc_paused +); + +localparam QFB = 8; + +// check configuration +initial begin + if (MCF_PARAMS_SIZE < (PFC_ENABLE ? 18 : 2)) begin + $error("Error: MCF_PARAMS_SIZE too small for requested configuration (instance %m)"); + $finish; + end +end + +reg lfc_req_reg = 1'b0, lfc_req_next; +reg [7:0] pfc_req_reg = 8'd0, pfc_req_next; + +reg [16+QFB-1:0] lfc_quanta_reg = 0, lfc_quanta_next; +reg [16+QFB-1:0] pfc_quanta_reg[0:7], pfc_quanta_next[0:7]; + +reg stat_rx_lfc_pkt_reg = 1'b0, stat_rx_lfc_pkt_next; +reg stat_rx_lfc_xon_reg = 1'b0, stat_rx_lfc_xon_next; +reg stat_rx_lfc_xoff_reg = 1'b0, stat_rx_lfc_xoff_next; +reg stat_rx_pfc_pkt_reg = 1'b0, stat_rx_pfc_pkt_next; +reg [7:0] stat_rx_pfc_xon_reg = 0, stat_rx_pfc_xon_next; +reg [7:0] stat_rx_pfc_xoff_reg = 0, stat_rx_pfc_xoff_next; + +assign rx_lfc_req = lfc_req_reg; +assign rx_pfc_req = pfc_req_reg; + +assign stat_rx_lfc_pkt = stat_rx_lfc_pkt_reg; +assign stat_rx_lfc_xon = stat_rx_lfc_xon_reg; +assign stat_rx_lfc_xoff = stat_rx_lfc_xoff_reg; +assign stat_rx_lfc_paused = lfc_req_reg; +assign stat_rx_pfc_pkt = stat_rx_pfc_pkt_reg; +assign stat_rx_pfc_xon = stat_rx_pfc_xon_reg; +assign stat_rx_pfc_xoff = stat_rx_pfc_xoff_reg; +assign stat_rx_pfc_paused = pfc_req_reg; + +integer k; + +initial begin + for (k = 0; k < 8; k = k + 1) begin + pfc_quanta_reg[k] = 0; + end +end + +always @* begin + stat_rx_lfc_pkt_next = 1'b0; + stat_rx_lfc_xon_next = 1'b0; + stat_rx_lfc_xoff_next = 1'b0; + stat_rx_pfc_pkt_next = 1'b0; + stat_rx_pfc_xon_next = 0; + stat_rx_pfc_xoff_next = 0; + + if (cfg_quanta_clk_en && rx_lfc_ack) begin + if (lfc_quanta_reg > cfg_quanta_step) begin + lfc_quanta_next = lfc_quanta_reg - cfg_quanta_step; + end else begin + lfc_quanta_next = 0; + end + end else begin + lfc_quanta_next = lfc_quanta_reg; + end + + lfc_req_next = (lfc_quanta_reg != 0) && rx_lfc_en && cfg_rx_lfc_en; + + for (k = 0; k < 8; k = k + 1) begin + if (cfg_quanta_clk_en && rx_pfc_ack[k]) begin + if (pfc_quanta_reg[k] > cfg_quanta_step) begin + pfc_quanta_next[k] = pfc_quanta_reg[k] - cfg_quanta_step; + end else begin + pfc_quanta_next[k] = 0; + end + end else begin + pfc_quanta_next[k] = pfc_quanta_reg[k]; + end + + pfc_req_next[k] = (pfc_quanta_reg[k] != 0) && rx_pfc_en[k] && cfg_rx_pfc_en; + end + + if (mcf_valid) begin + if (mcf_opcode == cfg_rx_lfc_opcode && cfg_rx_lfc_en) begin + stat_rx_lfc_pkt_next = 1'b1; + stat_rx_lfc_xon_next = {mcf_params[7:0], mcf_params[15:8]} == 0; + stat_rx_lfc_xoff_next = {mcf_params[7:0], mcf_params[15:8]} != 0; + lfc_quanta_next = {mcf_params[7:0], mcf_params[15:8], {QFB{1'b0}}}; + end else if (PFC_ENABLE && mcf_opcode == cfg_rx_pfc_opcode && cfg_rx_pfc_en) begin + stat_rx_pfc_pkt_next = 1'b1; + for (k = 0; k < 8; k = k + 1) begin + if (mcf_params[k+8]) begin + stat_rx_pfc_xon_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8]} == 0; + stat_rx_pfc_xoff_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8]} != 0; + pfc_quanta_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8], {QFB{1'b0}}}; + end + end + end + end +end + +always @(posedge clk) begin + lfc_req_reg <= lfc_req_next; + pfc_req_reg <= pfc_req_next; + + lfc_quanta_reg <= lfc_quanta_next; + for (k = 0; k < 8; k = k + 1) begin + pfc_quanta_reg[k] <= pfc_quanta_next[k]; + end + + stat_rx_lfc_pkt_reg <= stat_rx_lfc_pkt_next; + stat_rx_lfc_xon_reg <= stat_rx_lfc_xon_next; + stat_rx_lfc_xoff_reg <= stat_rx_lfc_xoff_next; + stat_rx_pfc_pkt_reg <= stat_rx_pfc_pkt_next; + stat_rx_pfc_xon_reg <= stat_rx_pfc_xon_next; + stat_rx_pfc_xoff_reg <= stat_rx_pfc_xoff_next; + + if (rst) begin + lfc_req_reg <= 1'b0; + pfc_req_reg <= 8'd0; + lfc_quanta_reg <= 0; + for (k = 0; k < 8; k = k + 1) begin + pfc_quanta_reg[k] <= 0; + end + + stat_rx_lfc_pkt_reg <= 1'b0; + stat_rx_lfc_xon_reg <= 1'b0; + stat_rx_lfc_xoff_reg <= 1'b0; + stat_rx_pfc_pkt_reg <= 1'b0; + stat_rx_pfc_xon_reg <= 0; + stat_rx_pfc_xoff_reg <= 0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/mac_pause_ctrl_tx.sv b/src/rvvi/mac_pause_ctrl_tx.sv new file mode 100644 index 000000000..20566d888 --- /dev/null +++ b/src/rvvi/mac_pause_ctrl_tx.sv @@ -0,0 +1,312 @@ +/* + +Copyright (c) 2023 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * PFC and pause frame transmit handling + */ +module mac_pause_ctrl_tx # +( + parameter MCF_PARAMS_SIZE = 18, + parameter PFC_ENABLE = 1 +) +( + input wire clk, + input wire rst, + + /* + * MAC control frame interface + */ + output wire mcf_valid, + input wire mcf_ready, + output wire [47:0] mcf_eth_dst, + output wire [47:0] mcf_eth_src, + output wire [15:0] mcf_eth_type, + output wire [15:0] mcf_opcode, + output wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, + + /* + * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) + */ + input wire tx_lfc_req, + input wire tx_lfc_resend, + + /* + * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) + */ + input wire [7:0] tx_pfc_req, + input wire tx_pfc_resend, + + /* + * Configuration + */ + input wire [47:0] cfg_tx_lfc_eth_dst, + input wire [47:0] cfg_tx_lfc_eth_src, + input wire [15:0] cfg_tx_lfc_eth_type, + input wire [15:0] cfg_tx_lfc_opcode, + input wire cfg_tx_lfc_en, + input wire [15:0] cfg_tx_lfc_quanta, + input wire [15:0] cfg_tx_lfc_refresh, + input wire [47:0] cfg_tx_pfc_eth_dst, + input wire [47:0] cfg_tx_pfc_eth_src, + input wire [15:0] cfg_tx_pfc_eth_type, + input wire [15:0] cfg_tx_pfc_opcode, + input wire cfg_tx_pfc_en, + input wire [8*16-1:0] cfg_tx_pfc_quanta, + input wire [8*16-1:0] cfg_tx_pfc_refresh, + input wire [9:0] cfg_quanta_step, + input wire cfg_quanta_clk_en, + + /* + * Status + */ + output wire stat_tx_lfc_pkt, + output wire stat_tx_lfc_xon, + output wire stat_tx_lfc_xoff, + output wire stat_tx_lfc_paused, + output wire stat_tx_pfc_pkt, + output wire [7:0] stat_tx_pfc_xon, + output wire [7:0] stat_tx_pfc_xoff, + output wire [7:0] stat_tx_pfc_paused +); + +localparam QFB = 8; + +// check configuration +initial begin + if (MCF_PARAMS_SIZE < (PFC_ENABLE ? 18 : 2)) begin + $error("Error: MCF_PARAMS_SIZE too small for requested configuration (instance %m)"); + $finish; + end +end + +reg lfc_req_reg = 1'b0, lfc_req_next; +reg lfc_act_reg = 1'b0, lfc_act_next; +reg lfc_send_reg = 1'b0, lfc_send_next; +reg [7:0] pfc_req_reg = 8'd0, pfc_req_next; +reg [7:0] pfc_act_reg = 8'd0, pfc_act_next; +reg [7:0] pfc_en_reg = 8'd0, pfc_en_next; +reg pfc_send_reg = 1'b0, pfc_send_next; + +reg [16+QFB-1:0] lfc_refresh_reg = 0, lfc_refresh_next; +reg [16+QFB-1:0] pfc_refresh_reg[0:7], pfc_refresh_next[0:7]; + +reg stat_tx_lfc_pkt_reg = 1'b0, stat_tx_lfc_pkt_next; +reg stat_tx_lfc_xon_reg = 1'b0, stat_tx_lfc_xon_next; +reg stat_tx_lfc_xoff_reg = 1'b0, stat_tx_lfc_xoff_next; +reg stat_tx_pfc_pkt_reg = 1'b0, stat_tx_pfc_pkt_next; +reg [7:0] stat_tx_pfc_xon_reg = 0, stat_tx_pfc_xon_next; +reg [7:0] stat_tx_pfc_xoff_reg = 0, stat_tx_pfc_xoff_next; + +// MAC control interface +reg mcf_pfc_sel_reg = PFC_ENABLE != 0, mcf_pfc_sel_next; +reg mcf_valid_reg = 1'b0, mcf_valid_next; + +wire [2*8-1:0] mcf_lfc_params; +assign mcf_lfc_params[16*0 +: 16] = lfc_req_reg ? {cfg_tx_lfc_quanta[0 +: 8], cfg_tx_lfc_quanta[8 +: 8]} : 0; + +wire [18*8-1:0] mcf_pfc_params; +assign mcf_pfc_params[16*0 +: 16] = {pfc_en_reg, 8'd0}; +assign mcf_pfc_params[16*1 +: 16] = pfc_req_reg[0] ? {cfg_tx_pfc_quanta[16*0+0 +: 8], cfg_tx_pfc_quanta[16*0+8 +: 8]} : 0; +assign mcf_pfc_params[16*2 +: 16] = pfc_req_reg[1] ? {cfg_tx_pfc_quanta[16*1+0 +: 8], cfg_tx_pfc_quanta[16*1+8 +: 8]} : 0; +assign mcf_pfc_params[16*3 +: 16] = pfc_req_reg[2] ? {cfg_tx_pfc_quanta[16*2+0 +: 8], cfg_tx_pfc_quanta[16*2+8 +: 8]} : 0; +assign mcf_pfc_params[16*4 +: 16] = pfc_req_reg[3] ? {cfg_tx_pfc_quanta[16*3+0 +: 8], cfg_tx_pfc_quanta[16*3+8 +: 8]} : 0; +assign mcf_pfc_params[16*5 +: 16] = pfc_req_reg[4] ? {cfg_tx_pfc_quanta[16*4+0 +: 8], cfg_tx_pfc_quanta[16*4+8 +: 8]} : 0; +assign mcf_pfc_params[16*6 +: 16] = pfc_req_reg[5] ? {cfg_tx_pfc_quanta[16*5+0 +: 8], cfg_tx_pfc_quanta[16*5+8 +: 8]} : 0; +assign mcf_pfc_params[16*7 +: 16] = pfc_req_reg[6] ? {cfg_tx_pfc_quanta[16*6+0 +: 8], cfg_tx_pfc_quanta[16*6+8 +: 8]} : 0; +assign mcf_pfc_params[16*8 +: 16] = pfc_req_reg[7] ? {cfg_tx_pfc_quanta[16*7+0 +: 8], cfg_tx_pfc_quanta[16*7+8 +: 8]} : 0; + +assign mcf_valid = mcf_valid_reg; +assign mcf_eth_dst = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_dst : cfg_tx_lfc_eth_dst; +assign mcf_eth_src = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_src : cfg_tx_lfc_eth_src; +assign mcf_eth_type = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_type : cfg_tx_lfc_eth_type; +assign mcf_opcode = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_opcode : cfg_tx_lfc_opcode; +assign mcf_params = (PFC_ENABLE && mcf_pfc_sel_reg) ? mcf_pfc_params : mcf_lfc_params; + +assign stat_tx_lfc_pkt = stat_tx_lfc_pkt_reg; +assign stat_tx_lfc_xon = stat_tx_lfc_xon_reg; +assign stat_tx_lfc_xoff = stat_tx_lfc_xoff_reg; +assign stat_tx_lfc_paused = lfc_req_reg; +assign stat_tx_pfc_pkt = stat_tx_pfc_pkt_reg; +assign stat_tx_pfc_xon = stat_tx_pfc_xon_reg; +assign stat_tx_pfc_xoff = stat_tx_pfc_xoff_reg; +assign stat_tx_pfc_paused = pfc_req_reg; + +integer k; + +initial begin + for (k = 0; k < 8; k = k + 1) begin + pfc_refresh_reg[k] = 0; + end +end + +always @* begin + lfc_req_next = lfc_req_reg; + lfc_act_next = lfc_act_reg; + lfc_send_next = lfc_send_reg | tx_lfc_resend; + pfc_req_next = pfc_req_reg; + pfc_act_next = pfc_act_reg; + pfc_en_next = pfc_en_reg; + pfc_send_next = pfc_send_reg | tx_pfc_resend; + + mcf_pfc_sel_next = mcf_pfc_sel_reg; + mcf_valid_next = mcf_valid_reg && !mcf_ready; + + stat_tx_lfc_pkt_next = 1'b0; + stat_tx_lfc_xon_next = 1'b0; + stat_tx_lfc_xoff_next = 1'b0; + stat_tx_pfc_pkt_next = 1'b0; + stat_tx_pfc_xon_next = 0; + stat_tx_pfc_xoff_next = 0; + + if (cfg_quanta_clk_en) begin + if (lfc_refresh_reg > cfg_quanta_step) begin + lfc_refresh_next = lfc_refresh_reg - cfg_quanta_step; + end else begin + lfc_refresh_next = 0; + if (lfc_req_reg) begin + lfc_send_next = 1'b1; + end + end + end else begin + lfc_refresh_next = lfc_refresh_reg; + end + + for (k = 0; k < 8; k = k + 1) begin + if (cfg_quanta_clk_en) begin + if (pfc_refresh_reg[k] > cfg_quanta_step) begin + pfc_refresh_next[k] = pfc_refresh_reg[k] - cfg_quanta_step; + end else begin + pfc_refresh_next[k] = 0; + if (pfc_req_reg[k]) begin + pfc_send_next = 1'b1; + end + end + end else begin + pfc_refresh_next[k] = pfc_refresh_reg[k]; + end + end + + if (cfg_tx_lfc_en) begin + if (!mcf_valid_reg) begin + if (lfc_req_reg != tx_lfc_req) begin + lfc_req_next = tx_lfc_req; + lfc_act_next = lfc_act_reg | tx_lfc_req; + lfc_send_next = 1'b1; + end + + if (lfc_send_reg && !(PFC_ENABLE && cfg_tx_pfc_en && pfc_send_reg)) begin + mcf_pfc_sel_next = 1'b0; + mcf_valid_next = lfc_act_reg; + lfc_act_next = lfc_req_reg; + lfc_refresh_next = lfc_req_reg ? {cfg_tx_lfc_refresh, {QFB{1'b0}}} : 0; + lfc_send_next = 1'b0; + + stat_tx_lfc_pkt_next = lfc_act_reg; + stat_tx_lfc_xon_next = lfc_act_reg && !lfc_req_reg; + stat_tx_lfc_xoff_next = lfc_act_reg && lfc_req_reg; + end + end + end + + if (PFC_ENABLE && cfg_tx_pfc_en) begin + if (!mcf_valid_reg) begin + if (pfc_req_reg != tx_pfc_req) begin + pfc_req_next = tx_pfc_req; + pfc_act_next = pfc_act_reg | tx_pfc_req; + pfc_send_next = 1'b1; + end + + if (pfc_send_reg) begin + mcf_pfc_sel_next = 1'b1; + mcf_valid_next = pfc_act_reg != 0; + pfc_en_next = pfc_act_reg; + pfc_act_next = pfc_req_reg; + for (k = 0; k < 8; k = k + 1) begin + pfc_refresh_next[k] = pfc_req_reg[k] ? {cfg_tx_pfc_refresh[16*k +: 16], {QFB{1'b0}}} : 0; + end + pfc_send_next = 1'b0; + + stat_tx_pfc_pkt_next = pfc_act_reg != 0; + stat_tx_pfc_xon_next = pfc_act_reg & ~pfc_req_reg; + stat_tx_pfc_xoff_next = pfc_act_reg & pfc_req_reg; + end + end + end +end + +always @(posedge clk) begin + lfc_req_reg <= lfc_req_next; + lfc_act_reg <= lfc_act_next; + lfc_send_reg <= lfc_send_next; + pfc_req_reg <= pfc_req_next; + pfc_act_reg <= pfc_act_next; + pfc_en_reg <= pfc_en_next; + pfc_send_reg <= pfc_send_next; + + mcf_pfc_sel_reg <= mcf_pfc_sel_next; + mcf_valid_reg <= mcf_valid_next; + + lfc_refresh_reg <= lfc_refresh_next; + for (k = 0; k < 8; k = k + 1) begin + pfc_refresh_reg[k] <= pfc_refresh_next[k]; + end + + stat_tx_lfc_pkt_reg <= stat_tx_lfc_pkt_next; + stat_tx_lfc_xon_reg <= stat_tx_lfc_xon_next; + stat_tx_lfc_xoff_reg <= stat_tx_lfc_xoff_next; + stat_tx_pfc_pkt_reg <= stat_tx_pfc_pkt_next; + stat_tx_pfc_xon_reg <= stat_tx_pfc_xon_next; + stat_tx_pfc_xoff_reg <= stat_tx_pfc_xoff_next; + + if (rst) begin + lfc_req_reg <= 1'b0; + lfc_act_reg <= 1'b0; + lfc_send_reg <= 1'b0; + pfc_req_reg <= 0; + pfc_act_reg <= 0; + pfc_send_reg <= 0; + mcf_pfc_sel_reg <= PFC_ENABLE != 0; + mcf_valid_reg <= 1'b0; + lfc_refresh_reg <= 0; + for (k = 0; k < 8; k = k + 1) begin + pfc_refresh_reg[k] <= 0; + end + + stat_tx_lfc_pkt_reg <= 1'b0; + stat_tx_lfc_xon_reg <= 1'b0; + stat_tx_lfc_xoff_reg <= 1'b0; + stat_tx_pfc_pkt_reg <= 1'b0; + stat_tx_pfc_xon_reg <= 0; + stat_tx_pfc_xoff_reg <= 0; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/mii_phy_if.sv b/src/rvvi/mii_phy_if.sv new file mode 100644 index 000000000..340d7ad24 --- /dev/null +++ b/src/rvvi/mii_phy_if.sv @@ -0,0 +1,140 @@ +/* + +Copyright (c) 2019 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * MII PHY interface + */ +module mii_phy_if # +( + // target ("SIM", "GENERIC", "XILINX", "ALTERA") + parameter TARGET = "GENERIC", + // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") + // Use BUFR for Virtex-5, Virtex-6, 7-series + // Use BUFG for Ultrascale + // Use BUFIO2 for Spartan-6 + parameter CLOCK_INPUT_STYLE = "BUFIO2" +) +( + input wire rst, + + /* + * MII interface to MAC + */ + output wire mac_mii_rx_clk, + output wire mac_mii_rx_rst, + output wire [3:0] mac_mii_rxd, + output wire mac_mii_rx_dv, + output wire mac_mii_rx_er, + output wire mac_mii_tx_clk, + output wire mac_mii_tx_rst, + input wire [3:0] mac_mii_txd, + input wire mac_mii_tx_en, + input wire mac_mii_tx_er, + + /* + * MII interface to PHY + */ + input wire phy_mii_rx_clk, + input wire [3:0] phy_mii_rxd, + input wire phy_mii_rx_dv, + input wire phy_mii_rx_er, + input wire phy_mii_tx_clk, + output wire [3:0] phy_mii_txd, + output wire phy_mii_tx_en, + output wire phy_mii_tx_er +); + +ssio_sdr_in # +( + .TARGET(TARGET), + .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), + .WIDTH(6) +) +rx_ssio_sdr_inst ( + .input_clk(phy_mii_rx_clk), + .input_d({phy_mii_rxd, phy_mii_rx_dv, phy_mii_rx_er}), + .output_clk(mac_mii_rx_clk), + .output_q({mac_mii_rxd, mac_mii_rx_dv, mac_mii_rx_er}) +); + +(* IOB = "TRUE" *) +reg [3:0] phy_mii_txd_reg = 4'd0; +(* IOB = "TRUE" *) +reg phy_mii_tx_en_reg = 1'b0, phy_mii_tx_er_reg = 1'b0; + +assign phy_mii_txd = phy_mii_txd_reg; +assign phy_mii_tx_en = phy_mii_tx_en_reg; +assign phy_mii_tx_er = phy_mii_tx_er_reg; + +always @(posedge mac_mii_tx_clk) begin + phy_mii_txd_reg <= mac_mii_txd; + phy_mii_tx_en_reg <= mac_mii_tx_en; + phy_mii_tx_er_reg <= mac_mii_tx_er; +end + +generate + +if (TARGET == "XILINX") begin + BUFG + mii_bufg_inst ( + .I(phy_mii_tx_clk), + .O(mac_mii_tx_clk) + ); +end else begin + assign mac_mii_tx_clk = phy_mii_tx_clk; +end + +endgenerate + +// reset sync +reg [3:0] tx_rst_reg = 4'hf; +assign mac_mii_tx_rst = tx_rst_reg[0]; + +always @(posedge mac_mii_tx_clk or posedge rst) begin + if (rst) begin + tx_rst_reg <= 4'hf; + end else begin + tx_rst_reg <= {1'b0, tx_rst_reg[3:1]}; + end +end + +reg [3:0] rx_rst_reg = 4'hf; +assign mac_mii_rx_rst = rx_rst_reg[0]; + +always @(posedge mac_mii_rx_clk or posedge rst) begin + if (rst) begin + rx_rst_reg <= 4'hf; + end else begin + rx_rst_reg <= {1'b0, rx_rst_reg[3:1]}; + end +end + +endmodule + +`resetall diff --git a/src/rvvi/ssio_ddr_in.sv b/src/rvvi/ssio_ddr_in.sv new file mode 100644 index 000000000..5060f4d27 --- /dev/null +++ b/src/rvvi/ssio_ddr_in.sv @@ -0,0 +1,150 @@ +/* + +Copyright (c) 2016-2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * Generic source synchronous DDR input + */ +module ssio_ddr_in # +( + // target ("SIM", "GENERIC", "XILINX", "ALTERA") + parameter TARGET = "GENERIC", + // IODDR style ("IODDR", "IODDR2") + // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale + // Use IODDR2 for Spartan-6 + parameter IODDR_STYLE = "IODDR2", + // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") + // Use BUFR for Virtex-6, 7-series + // Use BUFG for Virtex-5, Spartan-6, Ultrascale + parameter CLOCK_INPUT_STYLE = "BUFG", + // Width of register in bits + parameter WIDTH = 1 +) +( + input wire input_clk, + + input wire [WIDTH-1:0] input_d, + + output wire output_clk, + + output wire [WIDTH-1:0] output_q1, + output wire [WIDTH-1:0] output_q2 +); + +wire clk_int; +wire clk_io; + +generate + +if (TARGET == "XILINX") begin + + // use Xilinx clocking primitives + + if (CLOCK_INPUT_STYLE == "BUFG") begin + + // buffer RX clock + BUFG + clk_bufg ( + .I(input_clk), + .O(clk_int) + ); + + // pass through RX clock to logic and input buffers + assign clk_io = clk_int; + assign output_clk = clk_int; + + end else if (CLOCK_INPUT_STYLE == "BUFR") begin + + assign clk_int = input_clk; + + // pass through RX clock to input buffers + BUFIO + clk_bufio ( + .I(clk_int), + .O(clk_io) + ); + + // pass through RX clock to logic + BUFR #( + .BUFR_DIVIDE("BYPASS") + ) + clk_bufr ( + .I(clk_int), + .O(output_clk), + .CE(1'b1), + .CLR(1'b0) + ); + + end else if (CLOCK_INPUT_STYLE == "BUFIO") begin + + assign clk_int = input_clk; + + // pass through RX clock to input buffers + BUFIO + clk_bufio ( + .I(clk_int), + .O(clk_io) + ); + + // pass through RX clock to MAC + BUFG + clk_bufg ( + .I(clk_int), + .O(output_clk) + ); + + end + +end else begin + + // pass through RX clock to input buffers + assign clk_io = input_clk; + + // pass through RX clock to logic + assign clk_int = input_clk; + assign output_clk = clk_int; + +end + +endgenerate + +iddr #( + .TARGET(TARGET), + .IODDR_STYLE(IODDR_STYLE), + .WIDTH(WIDTH) +) +data_iddr_inst ( + .clk(clk_io), + .d(input_d), + .q1(output_q1), + .q2(output_q2) +); + +endmodule + +`resetall diff --git a/src/rvvi/ssio_sdr_in.sv b/src/rvvi/ssio_sdr_in.sv new file mode 100644 index 000000000..351cadc1d --- /dev/null +++ b/src/rvvi/ssio_sdr_in.sv @@ -0,0 +1,166 @@ +/* + +Copyright (c) 2016-2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`default_nettype none + +/* + * Generic source synchronous SDR input + */ +module ssio_sdr_in # +( + // target ("SIM", "GENERIC", "XILINX", "ALTERA") + parameter TARGET = "GENERIC", + // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") + // Use BUFR for Virtex-5, Virtex-6, 7-series + // Use BUFG for Ultrascale + // Use BUFIO2 for Spartan-6 + parameter CLOCK_INPUT_STYLE = "BUFIO2", + // Width of register in bits + parameter WIDTH = 1 +) +( + input wire input_clk, + + input wire [WIDTH-1:0] input_d, + + output wire output_clk, + + output wire [WIDTH-1:0] output_q +); + +wire clk_int; +wire clk_io; + +generate + +if (TARGET == "XILINX") begin + + // use Xilinx clocking primitives + + if (CLOCK_INPUT_STYLE == "BUFG") begin + + // buffer RX clock + BUFG + clk_bufg ( + .I(input_clk), + .O(clk_int) + ); + + // pass through RX clock to logic and input buffers + assign clk_io = clk_int; + assign output_clk = clk_int; + + end else if (CLOCK_INPUT_STYLE == "BUFR") begin + + assign clk_int = input_clk; + + // pass through RX clock to input buffers + BUFIO + clk_bufio ( + .I(clk_int), + .O(clk_io) + ); + + // pass through RX clock to logic + BUFR #( + .BUFR_DIVIDE("BYPASS") + ) + clk_bufr ( + .I(clk_int), + .O(output_clk), + .CE(1'b1), + .CLR(1'b0) + ); + + end else if (CLOCK_INPUT_STYLE == "BUFIO") begin + + assign clk_int = input_clk; + + // pass through RX clock to input buffers + BUFIO + clk_bufio ( + .I(clk_int), + .O(clk_io) + ); + + // pass through RX clock to MAC + BUFG + clk_bufg ( + .I(clk_int), + .O(output_clk) + ); + + end else if (CLOCK_INPUT_STYLE == "BUFIO2") begin + + // pass through RX clock to input buffers + BUFIO2 #( + .DIVIDE(1), + .DIVIDE_BYPASS("TRUE"), + .I_INVERT("FALSE"), + .USE_DOUBLER("FALSE") + ) + clk_bufio ( + .I(input_clk), + .DIVCLK(clk_int), + .IOCLK(clk_io), + .SERDESSTROBE() + ); + + // pass through RX clock to MAC + BUFG + clk_bufg ( + .I(clk_int), + .O(output_clk) + ); + + end + +end else begin + + // pass through RX clock to input buffers + assign clk_io = input_clk; + + // pass through RX clock to logic + assign clk_int = input_clk; + assign output_clk = clk_int; + +end + +endgenerate + +(* IOB = "TRUE" *) +reg [WIDTH-1:0] output_q_reg = {WIDTH{1'b0}}; + +assign output_q = output_q_reg; + +always @(posedge clk_io) begin + output_q_reg <= input_d; +end + +endmodule + +`resetall From 6a4c8667df32fbe0bc7260edd6679e788bf832a6 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Thu, 30 May 2024 16:43:25 -0500 Subject: [PATCH 020/163] Added new signals to ILA to debug the RVVI tracer. The tracer appears to be stuck and the CPU is never getting out of (into reset). --- fpga/constraints/small-debug.xdc | 25 +++++++++++++++++++++++++ fpga/src/fpgaTopArtyA7.sv | 10 +++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index b73581ab7..62fcbe545 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -58,6 +58,31 @@ set_property port_width 64 [get_debug_ports u_ila_0/probe7] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] connect_debug_port u_ila_0/probe7 [get_nets [list {wallypipelinedsoc/core/lsu/WriteDataM[0]} {wallypipelinedsoc/core/lsu/WriteDataM[1]} {wallypipelinedsoc/core/lsu/WriteDataM[2]} {wallypipelinedsoc/core/lsu/WriteDataM[3]} {wallypipelinedsoc/core/lsu/WriteDataM[4]} {wallypipelinedsoc/core/lsu/WriteDataM[5]} {wallypipelinedsoc/core/lsu/WriteDataM[6]} {wallypipelinedsoc/core/lsu/WriteDataM[7]} {wallypipelinedsoc/core/lsu/WriteDataM[8]} {wallypipelinedsoc/core/lsu/WriteDataM[9]} {wallypipelinedsoc/core/lsu/WriteDataM[10]} {wallypipelinedsoc/core/lsu/WriteDataM[11]} {wallypipelinedsoc/core/lsu/WriteDataM[12]} {wallypipelinedsoc/core/lsu/WriteDataM[13]} {wallypipelinedsoc/core/lsu/WriteDataM[14]} {wallypipelinedsoc/core/lsu/WriteDataM[15]} {wallypipelinedsoc/core/lsu/WriteDataM[16]} {wallypipelinedsoc/core/lsu/WriteDataM[17]} {wallypipelinedsoc/core/lsu/WriteDataM[18]} {wallypipelinedsoc/core/lsu/WriteDataM[19]} {wallypipelinedsoc/core/lsu/WriteDataM[20]} {wallypipelinedsoc/core/lsu/WriteDataM[21]} {wallypipelinedsoc/core/lsu/WriteDataM[22]} {wallypipelinedsoc/core/lsu/WriteDataM[23]} {wallypipelinedsoc/core/lsu/WriteDataM[24]} {wallypipelinedsoc/core/lsu/WriteDataM[25]} {wallypipelinedsoc/core/lsu/WriteDataM[26]} {wallypipelinedsoc/core/lsu/WriteDataM[27]} {wallypipelinedsoc/core/lsu/WriteDataM[28]} {wallypipelinedsoc/core/lsu/WriteDataM[29]} {wallypipelinedsoc/core/lsu/WriteDataM[30]} {wallypipelinedsoc/core/lsu/WriteDataM[31]} {wallypipelinedsoc/core/lsu/WriteDataM[32]} {wallypipelinedsoc/core/lsu/WriteDataM[33]} {wallypipelinedsoc/core/lsu/WriteDataM[34]} {wallypipelinedsoc/core/lsu/WriteDataM[35]} {wallypipelinedsoc/core/lsu/WriteDataM[36]} {wallypipelinedsoc/core/lsu/WriteDataM[37]} {wallypipelinedsoc/core/lsu/WriteDataM[38]} {wallypipelinedsoc/core/lsu/WriteDataM[39]} {wallypipelinedsoc/core/lsu/WriteDataM[40]} {wallypipelinedsoc/core/lsu/WriteDataM[41]} {wallypipelinedsoc/core/lsu/WriteDataM[42]} {wallypipelinedsoc/core/lsu/WriteDataM[43]} {wallypipelinedsoc/core/lsu/WriteDataM[44]} {wallypipelinedsoc/core/lsu/WriteDataM[45]} {wallypipelinedsoc/core/lsu/WriteDataM[46]} {wallypipelinedsoc/core/lsu/WriteDataM[47]} {wallypipelinedsoc/core/lsu/WriteDataM[48]} {wallypipelinedsoc/core/lsu/WriteDataM[49]} {wallypipelinedsoc/core/lsu/WriteDataM[50]} {wallypipelinedsoc/core/lsu/WriteDataM[51]} {wallypipelinedsoc/core/lsu/WriteDataM[52]} {wallypipelinedsoc/core/lsu/WriteDataM[53]} {wallypipelinedsoc/core/lsu/WriteDataM[54]} {wallypipelinedsoc/core/lsu/WriteDataM[55]} {wallypipelinedsoc/core/lsu/WriteDataM[56]} {wallypipelinedsoc/core/lsu/WriteDataM[57]} {wallypipelinedsoc/core/lsu/WriteDataM[58]} {wallypipelinedsoc/core/lsu/WriteDataM[59]} {wallypipelinedsoc/core/lsu/WriteDataM[60]} {wallypipelinedsoc/core/lsu/WriteDataM[61]} {wallypipelinedsoc/core/lsu/WriteDataM[62]} {wallypipelinedsoc/core/lsu/WriteDataM[63]} ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe8] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] +connect_debug_port u_ila_0/probe8 [get_nets [list {RVVIStall}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe9] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] +connect_debug_port u_ila_0/probe9 [get_nets [list {valid}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe10] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] +connect_debug_port u_ila_0/probe10 [get_nets [list {RvviAxiWready}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe11] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] +connect_debug_port u_ila_0/probe11 [get_nets [list {RvviAxiWvalid}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe12] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe12] +connect_debug_port u_ila_0/probe12 [get_nets [list {bus_struct_reset}]] + # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] connect_debug_port dbg_hub/clk [get_nets CPUCLK] diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 295c62c38..8a6b08f47 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -78,7 +78,7 @@ module fpgaTop wire CPUCLK; wire c0_ddr4_ui_clk_sync_rst; - wire bus_struct_reset; +(* mark_debug = "true" *) wire bus_struct_reset; wire peripheral_reset; wire interconnect_aresetn; wire peripheral_aresetn; @@ -444,7 +444,7 @@ module fpgaTop wire [11:0] device_temp; wire mmcm1_locked; - logic RVVIStall; +(* mark_debug = "true" *) logic RVVIStall; assign GPIOIN = {28'b0, GPI}; assign GPO = GPIOOUT[4:0]; @@ -1116,7 +1116,7 @@ module fpgaTop .device_temp(device_temp)); localparam MAX_CSRS = 3; - logic valid; +(* mark_debug = "true" *) logic valid; logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .valid, .rvvi); @@ -1125,8 +1125,8 @@ module fpgaTop logic [31:0] RvviAxiWdata; logic [3:0] RvviAxiWstrb; logic RvviAxiWlast; - logic RvviAxiWvalid; - logic RvviAxiWready; +(* mark_debug = "true" *) logic RvviAxiWvalid; +(* mark_debug = "true" *) logic RvviAxiWready; logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; From 1df3e5239a56f8639b1539b7288f87e2384086af Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Thu, 30 May 2024 17:57:28 -0500 Subject: [PATCH 021/163] This is great. The FPGA is able to send ethernet frames consisting of the RVVI data to the host computer. wireshark is able to capture the frames and they match the expected data! --- src/rvvi/packetizer.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 93390d03b..1040e8593 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -71,7 +71,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, case(CurrState) STATE_RDY: if (TransReady & valid) NextState = STATE_TRANS; else if(~TransReady & valid) NextState = STATE_WAIT; - STATE_WAIT: if(TransReady) NextState = STATE_TRANS; + else NextState = STATE_RDY; + STATE_WAIT: if(TransReady) NextState = STATE_TRANS; else NextState = STATE_WAIT; STATE_TRANS: if(BurstDone) NextState = STATE_RDY; else NextState = STATE_TRANS; From 0dccc6051d14ec5ac01c0e75ff78e1d0f5032db7 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 31 May 2024 13:55:25 -0500 Subject: [PATCH 022/163] draft of receiving code to unpack the ethernet frames into rvvi. --- src/rvvi/packetizer.sv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 1040e8593..e1685192c 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -53,7 +53,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic WordCountEnable; logic [47:0] SrcMac, DstMac; logic [31:0] Tag; - logic [15:0] Length; + logic [15:0] EthType; logic [TotalFrameLengthBits-1:0] TotalFrame; logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; @@ -99,13 +99,13 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; end - assign TotalFrame = {rvviDelay, Length, Tag, DstMac, SrcMac}; + assign TotalFrame = {rvviDelay, EthType, Tag, DstMac, SrcMac}; // *** fix me later assign SrcMac = 48'h8F54_0000_1654; // made something up assign DstMac = 48'h4502_1111_6843; assign Tag = '0; - assign Length = BytesInFrame + 16'd6 + 16'd6 + 16'd4 + 16'd2; + assign Length = 16'h0801; assign RvviAxiWdata = TotalFrameWords[WordCount]; assign RvviAxiWstrb = '1; From e05ebc30b85460745a9a28f720c1418f87ca8e25 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 31 May 2024 16:48:41 -0500 Subject: [PATCH 023/163] Almost worked out the bugs in packetizer. --- src/rvvi/packetizer.sv | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index e1685192c..4a742f7da 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -52,8 +52,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic WordCountReset; logic WordCountEnable; logic [47:0] SrcMac, DstMac; - logic [31:0] Tag; logic [15:0] EthType; + logic [31:0] Tag; logic [TotalFrameLengthBits-1:0] TotalFrame; logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; @@ -91,7 +91,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, counter #(10) WordCounter(m_axi_aclk, WordCountReset, WordCountEnable, WordCount); // *** BUG BytesInFrame will eventually depend on the length of the data stored into the ethernet frame // for now this will be exactly 608 bits (76 bytes, 19 words) - assign BytesInFrame = 12'd76; + assign BytesInFrame = 12'd2 + 12'd76 + 12'd6 + 12'd6 + 12'd2; assign BurstDone = WordCount == (BytesInFrame[11:2] - 1'b1); genvar index; @@ -99,13 +99,13 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; end - assign TotalFrame = {rvviDelay, EthType, Tag, DstMac, SrcMac}; + assign TotalFrame = {16'b0, rvviDelay, 4'b0, BytesInFrame, DstMac, SrcMac}; // *** fix me later - assign SrcMac = 48'h8F54_0000_1654; // made something up - assign DstMac = 48'h4502_1111_6843; - assign Tag = '0; - assign Length = 16'h0801; + assign DstMac = 48'h8F54_0000_1654; // made something up + assign SrcMac = 48'h4502_1111_6843; + assign Tag = 32'b0; + assign EthType = 16'h0801; assign RvviAxiWdata = TotalFrameWords[WordCount]; assign RvviAxiWstrb = '1; From a830bd57f0b58ba8bc98af16e6a64f03bf9e5c8c Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 31 May 2024 17:46:43 -0500 Subject: [PATCH 024/163] Have to reverse the byte order for ethernet frame length. --- src/rvvi/packetizer.sv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 4a742f7da..48db68f76 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -54,6 +54,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic [47:0] SrcMac, DstMac; logic [15:0] EthType; logic [31:0] Tag; + logic [15:0] Length; logic [TotalFrameLengthBits-1:0] TotalFrame; logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; @@ -99,7 +100,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; end - assign TotalFrame = {16'b0, rvviDelay, 4'b0, BytesInFrame, DstMac, SrcMac}; + assign Length = {BytesInFrame[7:0], 4'b0, BytesInFrame[11:8]}; + assign TotalFrame = {16'b0, rvviDelay, Length, DstMac, SrcMac}; // *** fix me later assign DstMac = 48'h8F54_0000_1654; // made something up From dc904cdbbb9a99692667e2a6114e5b819c1ee1d2 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 3 Jun 2024 18:10:25 -0500 Subject: [PATCH 025/163] The ethernet frame is mostly formatted correctly. Just need to reverse the byte order in the Ethernet length/type field. --- src/rvvi/packetizer.sv | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 48db68f76..4a742f7da 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -54,7 +54,6 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic [47:0] SrcMac, DstMac; logic [15:0] EthType; logic [31:0] Tag; - logic [15:0] Length; logic [TotalFrameLengthBits-1:0] TotalFrame; logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; @@ -100,8 +99,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; end - assign Length = {BytesInFrame[7:0], 4'b0, BytesInFrame[11:8]}; - assign TotalFrame = {16'b0, rvviDelay, Length, DstMac, SrcMac}; + assign TotalFrame = {16'b0, rvviDelay, 4'b0, BytesInFrame, DstMac, SrcMac}; // *** fix me later assign DstMac = 48'h8F54_0000_1654; // made something up From 80f98b3223ac54b1199ef4ecf2de68427407508a Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 4 Jun 2024 10:20:51 -0500 Subject: [PATCH 026/163] now have a working ethernet daemon to collect frames and partially decode into RVVI. --- fpga/rvvidaemon/rvvidaemon.c | 145 +++++++++++++++++++++++++++++++++++ src/rvvi/packetizer.sv | 7 +- 2 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 fpga/rvvidaemon/rvvidaemon.c diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c new file mode 100644 index 000000000..b4be770ca --- /dev/null +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -0,0 +1,145 @@ +/////////////////////////////////////////// +// rvvi daemon +// +// Written: Rose Thomposn ross1728@gmail.com +// Created: 31 May 2024 +// Modified: 31 May 2024 +// +// Purpose: Converts raw socket into rvvi interface to connect into ImperasDV +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// https://github.com/openhwgroup/cvw +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + + +#include <arpa/inet.h> +#include <linux/if_packet.h> +#include <linux/ip.h> +#include <linux/udp.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/ether.h> + + +#define DEST_MAC0 0x43 +#define DEST_MAC1 0x68 +#define DEST_MAC2 0x11 +#define DEST_MAC3 0x11 +#define DEST_MAC4 0x02 +#define DEST_MAC5 0x45 + +#define SRC_MAC0 0x54 +#define SRC_MAC1 0x16 +#define SRC_MAC2 0x00 +#define SRC_MAC3 0x00 +#define SRC_MAC4 0x54 +#define SRC_MAC5 0x8F + +#define BUF_SIZ 1024 + +//#define ETHER_TYPE 0x0801 // The type defined in packetizer.sv +#define ETHER_TYPE 0x5c00 // The type defined in packetizer.sv +//#define ETHER_TYPE 0x0000 // The type defined in packetizer.sv +#define DEFAULT_IF "eno1" + +void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn); + +int main(int argc, char **argv){ + + if(argc != 2){ + printf("Wrong number of arguments.\n"); + printf("rvvidaemon <ethernet device>\n"); + return -1; + } + + char sender[INET6_ADDRSTRLEN]; + int sockfd; + struct ifreq if_idx; + uint8_t buf[BUF_SIZ]; + int sockopt; + struct ifreq ifopts; /* set promiscuous mode */ + struct ether_header *eh = (struct ether_header *) buf; + ssize_t headerbytes, numbytes, payloadbytes; + + /* Open RAW socket to receive frames */ + if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) { + perror("socket"); + } + printf("Here 0\n"); + + /* Set interface to promiscuous mode - do we need to do this every time? */ + strncpy(ifopts.ifr_name, argv[1], IFNAMSIZ-1); + ioctl(sockfd, SIOCGIFFLAGS, &ifopts); + printf("Here 1\n"); + ifopts.ifr_flags |= IFF_PROMISC; + ioctl(sockfd, SIOCSIFFLAGS, &ifopts); + printf("Here 2\n"); + + /* Allow the socket to be reused - incase connection is closed prematurely */ + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) { + perror("setsockopt"); + close(sockfd); + exit(EXIT_FAILURE); + } + printf("Here 3\n"); + + /* Bind to device */ + if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, argv[1], IFNAMSIZ-1) == -1) { + perror("SO_BINDTODEVICE"); + close(sockfd); + exit(EXIT_FAILURE); + } + printf("Here 4\n"); + + while(1) { + printf("listener: Waiting to recvfrom...\n"); + numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL); + headerbytes = (sizeof(struct ether_header)); + payloadbytes = numbytes - headerbytes; + printf("listener: got frame %lu bytes\n", numbytes); + printf("payload size: %lu bytes\n", payloadbytes); + if (eh->ether_dhost[0] == DEST_MAC0 && + eh->ether_dhost[1] == DEST_MAC1 && + eh->ether_dhost[2] == DEST_MAC2 && + eh->ether_dhost[3] == DEST_MAC3 && + eh->ether_dhost[4] == DEST_MAC4 && + eh->ether_dhost[5] == DEST_MAC5) { + printf("Correct destination MAC address\n"); + uint64_t PC; + uint32_t insn; + DecodeRVVI(buf + headerbytes, &PC, &insn); + printf("PC = %lx, insn = %x\n", PC, insn); + } + } + + close(sockfd); + + return 0; +} + +void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ + // you know this actually easiser in assembly. :( + *PC = *((uint64_t *) payload); + *insn = *((uint32_t *) (payload + 8)); +} diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 4a742f7da..a1f62ba9f 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -52,7 +52,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic WordCountReset; logic WordCountEnable; logic [47:0] SrcMac, DstMac; - logic [15:0] EthType; + logic [15:0] EthType, Length; logic [31:0] Tag; logic [TotalFrameLengthBits-1:0] TotalFrame; logic [31:0] TotalFrameWords [TotalFrameLengthBytes/4-1:0]; @@ -90,7 +90,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, counter #(10) WordCounter(m_axi_aclk, WordCountReset, WordCountEnable, WordCount); // *** BUG BytesInFrame will eventually depend on the length of the data stored into the ethernet frame - // for now this will be exactly 608 bits (76 bytes, 19 words) + // for now this will be exactly 608 bits (76 bytes, 19 words) + the ethernet frame overhead and 2-byte padding = 92-bytes assign BytesInFrame = 12'd2 + 12'd76 + 12'd6 + 12'd6 + 12'd2; assign BurstDone = WordCount == (BytesInFrame[11:2] - 1'b1); @@ -99,7 +99,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TotalFrameWords[index] = TotalFrame[(index*32)+32-1 : (index*32)]; end - assign TotalFrame = {16'b0, rvviDelay, 4'b0, BytesInFrame, DstMac, SrcMac}; + assign Length = {4'b0, BytesInFrame}; + assign TotalFrame = {16'b0, rvviDelay, Length[7:0], Length[15:8], DstMac, SrcMac}; // *** fix me later assign DstMac = 48'h8F54_0000_1654; // made something up From fc62f804071d2a3ba49e0d39df1bd537d209359e Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 4 Jun 2024 11:31:05 -0500 Subject: [PATCH 027/163] Closer to fully working hardware tracer. --- src/rvvi/packetizer.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index a1f62ba9f..5b16615a6 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -100,13 +100,13 @@ module packetizer import cvw::*; #(parameter cvw_t P, end assign Length = {4'b0, BytesInFrame}; - assign TotalFrame = {16'b0, rvviDelay, Length[7:0], Length[15:8], DstMac, SrcMac}; + assign TotalFrame = {16'b0, rvviDelay, EthType, DstMac, SrcMac}; // *** fix me later assign DstMac = 48'h8F54_0000_1654; // made something up assign SrcMac = 48'h4502_1111_6843; assign Tag = 32'b0; - assign EthType = 16'h0801; + assign EthType = 16'h005c; assign RvviAxiWdata = TotalFrameWords[WordCount]; assign RvviAxiWstrb = '1; From 08ff88f428b1b2a6c90406b66e2fdefd76467f8c Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 4 Jun 2024 11:47:46 -0500 Subject: [PATCH 028/163] On the way towards complete reconstruction of the RVVI trace. --- fpga/rvvidaemon/rvvidaemon.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index b4be770ca..13088a478 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -63,6 +63,20 @@ //#define ETHER_TYPE 0x0000 // The type defined in packetizer.sv #define DEFAULT_IF "eno1" + +typedef struct { + uint64_t PC; + uint32_t insn; + uint64_t Mcycle; + uint64_t Minstret; + uint8_t Trap : 1; + uint8_t PrivilegeMode : 2; + uint8_t GPREn : 1; + uint8_t FPREn : 1; + uint16_t CSRCount : 12; +} RequiredRVVI_t; + + void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn); int main(int argc, char **argv){ @@ -140,6 +154,7 @@ int main(int argc, char **argv){ void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ // you know this actually easiser in assembly. :( - *PC = *((uint64_t *) payload); - *insn = *((uint32_t *) (payload + 8)); + RequiredRVVI_t *RequiredFields = (RequiredRVVI_t *) payload; + *PC = RequiredFields->PC; + *insn = RequiredFields->insn; } From 07d66c246c97542a3249dc8240e1813804881cb2 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 4 Jun 2024 11:59:17 -0500 Subject: [PATCH 029/163] Update. --- fpga/rvvidaemon/rvvidaemon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 13088a478..b3e5f97ea 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -157,4 +157,6 @@ void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ RequiredRVVI_t *RequiredFields = (RequiredRVVI_t *) payload; *PC = RequiredFields->PC; *insn = RequiredFields->insn; + if(RequiredFields->GPREn) + printf("Wrote a reg\n"); } From f0ed7807456e56cd58ac8c70c3997b4247bf2134 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 4 Jun 2024 15:11:03 -0500 Subject: [PATCH 030/163] progress. --- fpga/rvvidaemon/rvvidaemon.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index b3e5f97ea..7154b2410 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -74,8 +74,20 @@ typedef struct { uint8_t GPREn : 1; uint8_t FPREn : 1; uint16_t CSRCount : 12; -} RequiredRVVI_t; - +} RequiredRVVI_t; // total size is 241 bits or 30.25 bytes + +typedef struct { + uint8_t fill : 1; // *** depends on the size of the RequiredRVVI_t + uint8_t RegAddress : 5; + uint64_t RegValue; +} FirstReg_t; + +typedef struct { + uint8_t fill : 6; // *** depends on the size of the RequiredRVVI_t and FirstReg_t + uint8_t RegAddress : 5; + uint64_t RegValue; +} SecondReg_t; + void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn); @@ -127,23 +139,22 @@ int main(int argc, char **argv){ printf("Here 4\n"); while(1) { - printf("listener: Waiting to recvfrom...\n"); + //printf("listener: Waiting to recvfrom...\n"); numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL); headerbytes = (sizeof(struct ether_header)); payloadbytes = numbytes - headerbytes; - printf("listener: got frame %lu bytes\n", numbytes); - printf("payload size: %lu bytes\n", payloadbytes); + //printf("listener: got frame %lu bytes\n", numbytes); + //printf("payload size: %lu bytes\n", payloadbytes); if (eh->ether_dhost[0] == DEST_MAC0 && eh->ether_dhost[1] == DEST_MAC1 && eh->ether_dhost[2] == DEST_MAC2 && eh->ether_dhost[3] == DEST_MAC3 && eh->ether_dhost[4] == DEST_MAC4 && eh->ether_dhost[5] == DEST_MAC5) { - printf("Correct destination MAC address\n"); + //printf("Correct destination MAC address\n"); uint64_t PC; uint32_t insn; DecodeRVVI(buf + headerbytes, &PC, &insn); - printf("PC = %lx, insn = %x\n", PC, insn); } } @@ -155,8 +166,13 @@ int main(int argc, char **argv){ void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ // you know this actually easiser in assembly. :( RequiredRVVI_t *RequiredFields = (RequiredRVVI_t *) payload; + FirstReg_t FirstReg; + SecondReg_t SecondReg; *PC = RequiredFields->PC; *insn = RequiredFields->insn; - if(RequiredFields->GPREn) + printf("PC = %lx, insn = %x\n", *PC, *insn); + if(RequiredFields->GPREn){ + FirstReg = *(FirstReg_t *) (payload + sizeof(RequiredRVVI_t) - 1); printf("Wrote a reg\n"); + } } From 72c1374d9c826882a0046495b2bcbbc80e3d02e1 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 4 Jun 2024 15:11:57 -0500 Subject: [PATCH 031/163] Minor code cleanup. --- fpga/rvvidaemon/rvvidaemon.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 7154b2410..9d08883d0 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -99,9 +99,7 @@ int main(int argc, char **argv){ return -1; } - char sender[INET6_ADDRSTRLEN]; int sockfd; - struct ifreq if_idx; uint8_t buf[BUF_SIZ]; int sockopt; struct ifreq ifopts; /* set promiscuous mode */ From e16cf9d7392fb6ba47e9915ba63d0c4692d8ab35 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Mon, 10 Jun 2024 16:56:53 -0700 Subject: [PATCH 032/163] Added Makefile to compile rvvidaemon --- fpga/rvvidaemon/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 fpga/rvvidaemon/Makefile diff --git a/fpga/rvvidaemon/Makefile b/fpga/rvvidaemon/Makefile new file mode 100644 index 000000000..c1d1d5a1c --- /dev/null +++ b/fpga/rvvidaemon/Makefile @@ -0,0 +1,10 @@ +all: rvvidaemon + +rvvidaemon: rvvidaemon.o + gcc $^ -o rvvidaemon + +%.o:%.c + gcc -c $^ -o $@ + +clean: + rm *.o rvvidaemon From 49912589f537e33bc67d5f3267f41c0fefb48c0e Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Mon, 10 Jun 2024 17:57:24 -0700 Subject: [PATCH 033/163] Added rvviApi.h to rvvidaemon. --- fpga/rvvidaemon/rvvidaemon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 9d08883d0..48e83a6a7 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -40,6 +40,7 @@ #include <sys/socket.h> #include <net/if.h> #include <netinet/ether.h> +#include "rvviApi.h" // *** bug fix me when this file gets included into the correct directory. #define DEST_MAC0 0x43 From 3d9f796f21dd7a3ae16544b596128558c1cae2b8 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 11 Jun 2024 14:36:34 -0700 Subject: [PATCH 034/163] Better parsing of rvvi. --- fpga/rvvidaemon/rvvidaemon.c | 91 +++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 17 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 48e83a6a7..24732f181 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -75,22 +75,15 @@ typedef struct { uint8_t GPREn : 1; uint8_t FPREn : 1; uint16_t CSRCount : 12; -} RequiredRVVI_t; // total size is 241 bits or 30.25 bytes +} RequiredRVVI_t; // total size is 241 bits or 30.125 bytes typedef struct { - uint8_t fill : 1; // *** depends on the size of the RequiredRVVI_t uint8_t RegAddress : 5; uint64_t RegValue; -} FirstReg_t; - -typedef struct { - uint8_t fill : 6; // *** depends on the size of the RequiredRVVI_t and FirstReg_t - uint8_t RegAddress : 5; - uint64_t RegValue; -} SecondReg_t; - +} Reg_t; void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn); +void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); int main(int argc, char **argv){ @@ -164,14 +157,78 @@ int main(int argc, char **argv){ void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ // you know this actually easiser in assembly. :( + uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; + //int PayloadSize = sizeof(RequiredRVVI_t) - 1; + int PayloadSize = 30; + int Buf2Size = BUF_SIZ - PayloadSize; RequiredRVVI_t *RequiredFields = (RequiredRVVI_t *) payload; - FirstReg_t FirstReg; - SecondReg_t SecondReg; - *PC = RequiredFields->PC; - *insn = RequiredFields->insn; - printf("PC = %lx, insn = %x\n", *PC, *insn); + uint8_t *CurrentBytePointer = payload + PayloadSize; + Reg_t *FirstReg; + Reg_t SecondReg; + uint64_t Mcycle, Minstret; + // unforunately the struct appoarch does not work?!? + //*PC = RequiredFields->PC; + *PC = * (uint64_t *) payload; + //*insn = RequiredFields->insn; + payload += 8; + *insn = * (uint32_t *) payload; + // Mcycle = RequiredFields->Mcycle; + payload += 4; + Mcycle = * (uint64_t *) payload; + payload += 8; + Minstret = * (uint64_t *) payload; + //Minstret = RequiredFields->Minstret; + payload += 8; + // the next 4 bytes contain CSRCount (12), FPRWen(1), GPRWen(1), PrivilegeMode(2), Trap(1) + uint32_t RequiredFlags; + RequiredFlags = * (uint32_t *) payload; + uint8_t Trap, PrivilegeMode, GPRWen, FPRWen; + uint16_t CSRCount; + + Trap = RequiredFlags & 0x1; + PrivilegeMode = (RequiredFlags >> 1) & 0x3; + GPRWen = (RequiredFlags >> 3) & 0x1; + FPRWen = (RequiredFlags >> 4) & 0x1; + CSRCount = (RequiredFlags >> 5) & 0xFFF; + + int bits; + + printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", *PC, *insn, Mcycle, Minstret, Trap, PrivilegeMode, GPRWen, FPRWen, CSRCount); if(RequiredFields->GPREn){ - FirstReg = *(FirstReg_t *) (payload + sizeof(RequiredRVVI_t) - 1); - printf("Wrote a reg\n"); + BitShiftArray(buf2, CurrentBytePointer, 1, Buf2Size); + FirstReg = (Reg_t *) buf2; + printf("Wrote reg %d = %lx\n", FirstReg->RegAddress, FirstReg->RegValue); } + printf("!!!!!\n\n"); +} + +void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ + // always shift right by ShiftAmount (0 to 7 bit positions). + // *** this implemenation is very inefficient. improve later. + if(ShiftAmount < 0 || ShiftAmount > 7) return; + /* Read the first source byte + Read the second source byte + Right Shift byte 1 by ShiftAmount + Right Rotate byte 2 by ShiftAmount + Mask byte 2 by ~(2^ShiftAmount -1) + OR together the two bytes to form the final next byte + + repeat this for each byte + On the last byte we don't do the last steps + */ + int Index; + for(Index = 0; Index < Length - 1; Index++){ + uint8_t byte1 = src[Index]; + uint8_t byte2 = src[Index+1]; + byte1 = byte1 >> ShiftAmount; + uint8_t byte2rot = byte2 >> ShiftAmount | byte2 << (unsigned) (8 - ShiftAmount); + byte2rot = byte2rot & ~(2^ShiftAmount - 1); + uint8_t byte1final = byte2rot | byte1; + dst[Index] = byte1final; + } + // fence post + // For last one there is only one source byte + uint8_t byte1 = src[Length-1]; + byte1 = byte1 >> ShiftAmount; + dst[Length-1] = byte1; } From c9f3da51cbdabf1cbb8b9c3982a53dd541ecbac5 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 11 Jun 2024 15:35:35 -0700 Subject: [PATCH 035/163] getting closer to full reconstruction of rvvi. --- fpga/rvvidaemon/rvvidaemon.c | 56 ++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 24732f181..f7447d9dd 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -82,7 +82,7 @@ typedef struct { uint64_t RegValue; } Reg_t; -void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn); +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn); void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); int main(int argc, char **argv){ @@ -146,7 +146,7 @@ int main(int argc, char **argv){ //printf("Correct destination MAC address\n"); uint64_t PC; uint32_t insn; - DecodeRVVI(buf + headerbytes, &PC, &insn); + DecodeRVVI(buf + headerbytes, payloadbytes, &PC, &insn); } } @@ -155,35 +155,29 @@ int main(int argc, char **argv){ return 0; } -void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn){ // you know this actually easiser in assembly. :( uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; //int PayloadSize = sizeof(RequiredRVVI_t) - 1; int PayloadSize = 30; int Buf2Size = BUF_SIZ - PayloadSize; - RequiredRVVI_t *RequiredFields = (RequiredRVVI_t *) payload; - uint8_t *CurrentBytePointer = payload + PayloadSize; - Reg_t *FirstReg; - Reg_t SecondReg; uint64_t Mcycle, Minstret; // unforunately the struct appoarch does not work?!? - //*PC = RequiredFields->PC; *PC = * (uint64_t *) payload; - //*insn = RequiredFields->insn; payload += 8; *insn = * (uint32_t *) payload; - // Mcycle = RequiredFields->Mcycle; payload += 4; Mcycle = * (uint64_t *) payload; payload += 8; Minstret = * (uint64_t *) payload; - //Minstret = RequiredFields->Minstret; payload += 8; // the next 4 bytes contain CSRCount (12), FPRWen(1), GPRWen(1), PrivilegeMode(2), Trap(1) uint32_t RequiredFlags; RequiredFlags = * (uint32_t *) payload; uint8_t Trap, PrivilegeMode, GPRWen, FPRWen; uint16_t CSRCount; + uint8_t GPRReg; + uint64_t GPRData; Trap = RequiredFlags & 0x1; PrivilegeMode = (RequiredFlags >> 1) & 0x3; @@ -191,13 +185,38 @@ void DecodeRVVI(uint8_t *payload, uint64_t * PC, uint32_t *insn){ FPRWen = (RequiredFlags >> 4) & 0x1; CSRCount = (RequiredFlags >> 5) & 0xFFF; - int bits; - printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", *PC, *insn, Mcycle, Minstret, Trap, PrivilegeMode, GPRWen, FPRWen, CSRCount); - if(RequiredFields->GPREn){ - BitShiftArray(buf2, CurrentBytePointer, 1, Buf2Size); - FirstReg = (Reg_t *) buf2; - printf("Wrote reg %d = %lx\n", FirstReg->RegAddress, FirstReg->RegValue); + if(GPRWen || FPRWen || (CSRCount != 0)){ + payload += 2; + // the first bit of payload is the last bit of CSRCount. + ssize_t newPayloadSize = payloadsize - 30; + BitShiftArray(buf2, payload, 1, newPayloadSize); + int index; + printf("payload = "); + for(index = 0; index < 10; index++){ + printf("%02hhx", payload[index]); + } + printf("\n"); + printf("buf2 = "); + for(index = 0; index < 10; index++){ + printf("%02hhx", buf2[index]); + } + printf("\n"); + if(GPRWen){ + GPRReg = * (uint8_t *) buf2; + GPRReg = GPRReg & 0x1F; + BitShiftArray(buf3, buf2, 5, newPayloadSize); + GPRData = * (uint64_t *) buf3; + } + printf("Wrote register %d with value = %lx\n", GPRReg, GPRData); + int bits; + printf("Start at Reg data = "); + for(bits = 0; bits < newPayloadSize; bits++){ + printf("%02hhX", buf2[bits]); + } + printf("\n"); + + //printf("Wrote reg %d = %lx\n", FirstReg->RegAddress, FirstReg->RegValue); } printf("!!!!!\n\n"); } @@ -221,8 +240,7 @@ void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ uint8_t byte1 = src[Index]; uint8_t byte2 = src[Index+1]; byte1 = byte1 >> ShiftAmount; - uint8_t byte2rot = byte2 >> ShiftAmount | byte2 << (unsigned) (8 - ShiftAmount); - byte2rot = byte2rot & ~(2^ShiftAmount - 1); + uint8_t byte2rot = (byte2 << (unsigned) (8 - ShiftAmount)) & 0xff; uint8_t byte1final = byte2rot | byte1; dst[Index] = byte1final; } From 8bce2fc739d7d490f1a6d056e5373549ae85f627 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 11 Jun 2024 16:21:53 -0700 Subject: [PATCH 036/163] Getting closer. --- fpga/rvvidaemon/rvvidaemon.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index f7447d9dd..1b4a25d0e 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -158,6 +158,9 @@ int main(int argc, char **argv){ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn){ // you know this actually easiser in assembly. :( uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; + uint8_t * buf2ptr, *buf3ptr; + buf2ptr = buf2; + buf3ptr = buf3; //int PayloadSize = sizeof(RequiredRVVI_t) - 1; int PayloadSize = 30; int Buf2Size = BUF_SIZ - PayloadSize; @@ -175,9 +178,11 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * uint32_t RequiredFlags; RequiredFlags = * (uint32_t *) payload; uint8_t Trap, PrivilegeMode, GPRWen, FPRWen; - uint16_t CSRCount; - uint8_t GPRReg; - uint64_t GPRData; + uint16_t CSRCount = 0; + uint8_t GPRReg = 0; + uint64_t GPRData = 0; + uint8_t FPRReg = 0; + uint64_t FPRData = 0; Trap = RequiredFlags & 0x1; PrivilegeMode = (RequiredFlags >> 1) & 0x3; @@ -203,10 +208,22 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * } printf("\n"); if(GPRWen){ - GPRReg = * (uint8_t *) buf2; + GPRReg = * (uint8_t *) buf2ptr; GPRReg = GPRReg & 0x1F; - BitShiftArray(buf3, buf2, 5, newPayloadSize); + BitShiftArray(buf3, buf2ptr, 5, newPayloadSize); GPRData = * (uint64_t *) buf3; + if(FPRWen){ + buf3ptr += 8; + FPRReg = * (uint8_t *) buf3ptr; + BitShiftArray(buf2, buf3ptr, 5, newPayloadSize - 8); + FPRReg = FPRReg & 0x1F; + FPRData = * (uint64_t *) buf2; + } + }else if(FPRWen){ + FPRReg = * (uint8_t *) buf2; + FPRReg = FPRReg & 0x1F; + BitShiftArray(buf3, buf2, 5, newPayloadSize); + FPRData = * (uint64_t *) buf3; } printf("Wrote register %d with value = %lx\n", GPRReg, GPRData); int bits; From 3e7d07dfb6dc7f8f5c8aa71f6455af95f71911ca Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 11 Jun 2024 17:14:59 -0700 Subject: [PATCH 037/163] Better. --- fpga/rvvidaemon/rvvidaemon.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 1b4a25d0e..a1e6e0eb7 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -189,10 +189,10 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * GPRWen = (RequiredFlags >> 3) & 0x1; FPRWen = (RequiredFlags >> 4) & 0x1; CSRCount = (RequiredFlags >> 5) & 0xFFF; + payload += 2; printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", *PC, *insn, Mcycle, Minstret, Trap, PrivilegeMode, GPRWen, FPRWen, CSRCount); if(GPRWen || FPRWen || (CSRCount != 0)){ - payload += 2; // the first bit of payload is the last bit of CSRCount. ssize_t newPayloadSize = payloadsize - 30; BitShiftArray(buf2, payload, 1, newPayloadSize); @@ -232,6 +232,36 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * printf("%02hhX", buf2[bits]); } printf("\n"); + if(GPRWen ^ FPRWen){ + payload += 8; + Buf2Size = payloadsize - 38; + BitShiftArray(buf2, payload, 6, Buf2Size); + }else if(GPRWen & FPRWen){ + payload += 17; + Buf2Size = payloadsize - 47; + BitShiftArray(buf2, payload, 3, Buf2Size); + }else{ + Buf2Size = payloadsize - 30; + BitShiftArray(buf2, payload, 1, Buf2Size); + } + int CSRIndex; + uint8_t CSRWen[3] = {0, 0, 0}; + uint16_t CSRReg[3]; + uint64_t CSRValue[3]; + buf2ptr = buf2; + for(CSRIndex = 0; CSRIndex < CSRCount; CSRIndex++){ + CSRReg[CSRIndex] = (*(uint16_t *) buf2ptr) & 0xFFF; + Buf2Size -= 1; + BitShiftArray(buf3, buf2ptr + 1, 4, Buf2Size); + CSRValue[CSRIndex] = (*(uint64_t *) buf3); + CSRWen[CSRIndex] = 1; + buf2ptr = buf3; + } + for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ + if(CSRWen[CSRIndex]){ + printf("Wrote CSR %x with value %lx\n", CSRReg[CSRIndex], CSRValue[CSRIndex]); + } + } //printf("Wrote reg %d = %lx\n", FirstReg->RegAddress, FirstReg->RegValue); } From f5d4db68b17d6d663f60c5ab75f70c301ec64b6a Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 12 Jun 2024 08:56:16 -0700 Subject: [PATCH 038/163] Modified rvvidaemon to populate a struct with all the relavent fields. --- fpga/rvvidaemon/rvvidaemon.c | 40 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index a1e6e0eb7..fa7db2801 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -75,6 +75,14 @@ typedef struct { uint8_t GPREn : 1; uint8_t FPREn : 1; uint16_t CSRCount : 12; + uint8_t GPRReg : 5; + uint64_t GPRValue; + uint8_t FPRReg : 5; + uint64_t FPRValue; + uint8_t CSRWen[3]; + uint16_t CSRReg[3]; + uint64_t CSRValue[3]; + } RequiredRVVI_t; // total size is 241 bits or 30.125 bytes typedef struct { @@ -82,7 +90,7 @@ typedef struct { uint64_t RegValue; } Reg_t; -void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn); +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn, RequiredRVVI_t *InstructionData); void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); int main(int argc, char **argv){ @@ -146,7 +154,8 @@ int main(int argc, char **argv){ //printf("Correct destination MAC address\n"); uint64_t PC; uint32_t insn; - DecodeRVVI(buf + headerbytes, payloadbytes, &PC, &insn); + RequiredRVVI_t InstructionData; + DecodeRVVI(buf + headerbytes, payloadbytes, &PC, &insn, &InstructionData); } } @@ -155,7 +164,7 @@ int main(int argc, char **argv){ return 0; } -void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn){ +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn, RequiredRVVI_t *InstructionData){ // you know this actually easiser in assembly. :( uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; uint8_t * buf2ptr, *buf3ptr; @@ -183,6 +192,9 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * uint64_t GPRData = 0; uint8_t FPRReg = 0; uint64_t FPRData = 0; + uint8_t CSRWen[3] = {0, 0, 0}; + uint16_t CSRReg[3]; + uint64_t CSRValue[3]; Trap = RequiredFlags & 0x1; PrivilegeMode = (RequiredFlags >> 1) & 0x3; @@ -245,9 +257,6 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * BitShiftArray(buf2, payload, 1, Buf2Size); } int CSRIndex; - uint8_t CSRWen[3] = {0, 0, 0}; - uint16_t CSRReg[3]; - uint64_t CSRValue[3]; buf2ptr = buf2; for(CSRIndex = 0; CSRIndex < CSRCount; CSRIndex++){ CSRReg[CSRIndex] = (*(uint16_t *) buf2ptr) & 0xFFF; @@ -263,6 +272,25 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * } } + InstructionData->PC = *PC; + InstructionData->insn = *insn; + InstructionData->Mcycle = Mcycle; + InstructionData->Minstret = Minstret; + InstructionData->Trap = Trap; + InstructionData->PrivilegeMode = PrivilegeMode; + InstructionData->GPREn = GPRWen; + InstructionData->FPREn = FPRWen; + InstructionData->CSRCount = CSRCount; + InstructionData->GPRReg = GPRReg; + InstructionData->GPRValue = GPRData; + InstructionData->FPRReg = FPRReg; + InstructionData->FPRValue = FPRData; + for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ + InstructionData->CSRWen[CSRIndex] = CSRWen[CSRIndex]; + InstructionData->CSRReg[CSRIndex] = CSRReg[CSRIndex]; + InstructionData->CSRValue[CSRIndex] = CSRValue[CSRIndex]; + } + //printf("Wrote reg %d = %lx\n", FirstReg->RegAddress, FirstReg->RegValue); } printf("!!!!!\n\n"); From 323dbd348e7638c6c73644f18a2819471ba59dbf Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 12 Jun 2024 12:54:21 -0700 Subject: [PATCH 039/163] Progress. --- fpga/rvvidaemon/rvvidaemon.c | 43 +++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index fa7db2801..1f083d165 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -36,6 +36,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <unistd.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> @@ -90,7 +91,7 @@ typedef struct { uint64_t RegValue; } Reg_t; -void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn, RequiredRVVI_t *InstructionData); +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData); void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); int main(int argc, char **argv){ @@ -138,6 +139,14 @@ int main(int argc, char **argv){ } printf("Here 4\n"); + if(!rvviVersionCheck(RVVI_API_VERSION)){ + printf("Bad RVVI_API_VERSION\n"); + } + + //rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); + + rvviRefInit(NULL); + while(1) { //printf("listener: Waiting to recvfrom...\n"); numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL); @@ -155,16 +164,18 @@ int main(int argc, char **argv){ uint64_t PC; uint32_t insn; RequiredRVVI_t InstructionData; - DecodeRVVI(buf + headerbytes, payloadbytes, &PC, &insn, &InstructionData); + DecodeRVVI(buf + headerbytes, payloadbytes, &InstructionData); } } close(sockfd); + + return 0; } -void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t *insn, RequiredRVVI_t *InstructionData){ +void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData){ // you know this actually easiser in assembly. :( uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; uint8_t * buf2ptr, *buf3ptr; @@ -174,10 +185,12 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * int PayloadSize = 30; int Buf2Size = BUF_SIZ - PayloadSize; uint64_t Mcycle, Minstret; + uint64_t PC; + uint32_t insn; // unforunately the struct appoarch does not work?!? - *PC = * (uint64_t *) payload; + PC = * (uint64_t *) payload; payload += 8; - *insn = * (uint32_t *) payload; + insn = * (uint32_t *) payload; payload += 4; Mcycle = * (uint64_t *) payload; payload += 8; @@ -203,7 +216,7 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * CSRCount = (RequiredFlags >> 5) & 0xFFF; payload += 2; - printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", *PC, *insn, Mcycle, Minstret, Trap, PrivilegeMode, GPRWen, FPRWen, CSRCount); + printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", PC, insn, Mcycle, Minstret, Trap, PrivilegeMode, GPRWen, FPRWen, CSRCount); if(GPRWen || FPRWen || (CSRCount != 0)){ // the first bit of payload is the last bit of CSRCount. ssize_t newPayloadSize = payloadsize - 30; @@ -272,8 +285,8 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * } } - InstructionData->PC = *PC; - InstructionData->insn = *insn; + InstructionData->PC = PC; + InstructionData->insn = insn; InstructionData->Mcycle = Mcycle; InstructionData->Minstret = Minstret; InstructionData->Trap = Trap; @@ -296,6 +309,20 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, uint64_t * PC, uint32_t * printf("!!!!!\n\n"); } +void PrintInstructionData(RequiredRVVI_t *InstructionData){ + int CSRIndex; + printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", + InstructionData->PC, InstructionData->insn, InstructionData->Mcycle, InstructionData->Minstret, InstructionData->Trap, InstructionData->PrivilegeMode, InstructionData->GPREn, InstructionData->FPREn, InstructionData->CSRCount); + if(InstructionData->GPREn){ + + } + for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ + if(InstructionData->CSRWen[CSRIndex]){ + printf("Wrote CSR %x with value %lx\n", InstructionData->CSRReg[CSRIndex], InstructionData->CSRValue[CSRIndex]); + } + } +} + void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ // always shift right by ShiftAmount (0 to 7 bit positions). // *** this implemenation is very inefficient. improve later. From c9f51df34a1bae8c9cb2f51ad6458b84e8cce385 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 12 Jun 2024 14:47:32 -0700 Subject: [PATCH 040/163] Fixed bug in rvvi reset. --- fpga/rvvidaemon/rvvidaemon.c | 87 ++++++++++++++---------------------- fpga/src/fpgaTopArtyA7.sv | 2 +- 2 files changed, 34 insertions(+), 55 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 1f083d165..54240e72b 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -93,6 +93,7 @@ typedef struct { void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData); void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); +void PrintInstructionData(RequiredRVVI_t *InstructionData); int main(int argc, char **argv){ @@ -139,13 +140,13 @@ int main(int argc, char **argv){ } printf("Here 4\n"); - if(!rvviVersionCheck(RVVI_API_VERSION)){ - printf("Bad RVVI_API_VERSION\n"); - } + /* if(!rvviVersionCheck(RVVI_API_VERSION)){ */ + /* printf("Bad RVVI_API_VERSION\n"); */ + /* } */ //rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); - rvviRefInit(NULL); + //rvviRefInit(NULL); while(1) { //printf("listener: Waiting to recvfrom...\n"); @@ -165,6 +166,7 @@ int main(int argc, char **argv){ uint32_t insn; RequiredRVVI_t InstructionData; DecodeRVVI(buf + headerbytes, payloadbytes, &InstructionData); + PrintInstructionData(&InstructionData); } } @@ -208,6 +210,7 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *Instructi uint8_t CSRWen[3] = {0, 0, 0}; uint16_t CSRReg[3]; uint64_t CSRValue[3]; + int CSRIndex; Trap = RequiredFlags & 0x1; PrivilegeMode = (RequiredFlags >> 1) & 0x3; @@ -216,22 +219,11 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *Instructi CSRCount = (RequiredFlags >> 5) & 0xFFF; payload += 2; - printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", PC, insn, Mcycle, Minstret, Trap, PrivilegeMode, GPRWen, FPRWen, CSRCount); if(GPRWen || FPRWen || (CSRCount != 0)){ // the first bit of payload is the last bit of CSRCount. ssize_t newPayloadSize = payloadsize - 30; BitShiftArray(buf2, payload, 1, newPayloadSize); int index; - printf("payload = "); - for(index = 0; index < 10; index++){ - printf("%02hhx", payload[index]); - } - printf("\n"); - printf("buf2 = "); - for(index = 0; index < 10; index++){ - printf("%02hhx", buf2[index]); - } - printf("\n"); if(GPRWen){ GPRReg = * (uint8_t *) buf2ptr; GPRReg = GPRReg & 0x1F; @@ -250,13 +242,6 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *Instructi BitShiftArray(buf3, buf2, 5, newPayloadSize); FPRData = * (uint64_t *) buf3; } - printf("Wrote register %d with value = %lx\n", GPRReg, GPRData); - int bits; - printf("Start at Reg data = "); - for(bits = 0; bits < newPayloadSize; bits++){ - printf("%02hhX", buf2[bits]); - } - printf("\n"); if(GPRWen ^ FPRWen){ payload += 8; Buf2Size = payloadsize - 38; @@ -269,7 +254,6 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *Instructi Buf2Size = payloadsize - 30; BitShiftArray(buf2, payload, 1, Buf2Size); } - int CSRIndex; buf2ptr = buf2; for(CSRIndex = 0; CSRIndex < CSRCount; CSRIndex++){ CSRReg[CSRIndex] = (*(uint16_t *) buf2ptr) & 0xFFF; @@ -279,48 +263,43 @@ void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *Instructi CSRWen[CSRIndex] = 1; buf2ptr = buf3; } - for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ - if(CSRWen[CSRIndex]){ - printf("Wrote CSR %x with value %lx\n", CSRReg[CSRIndex], CSRValue[CSRIndex]); - } - } - - InstructionData->PC = PC; - InstructionData->insn = insn; - InstructionData->Mcycle = Mcycle; - InstructionData->Minstret = Minstret; - InstructionData->Trap = Trap; - InstructionData->PrivilegeMode = PrivilegeMode; - InstructionData->GPREn = GPRWen; - InstructionData->FPREn = FPRWen; - InstructionData->CSRCount = CSRCount; - InstructionData->GPRReg = GPRReg; - InstructionData->GPRValue = GPRData; - InstructionData->FPRReg = FPRReg; - InstructionData->FPRValue = FPRData; - for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ - InstructionData->CSRWen[CSRIndex] = CSRWen[CSRIndex]; - InstructionData->CSRReg[CSRIndex] = CSRReg[CSRIndex]; - InstructionData->CSRValue[CSRIndex] = CSRValue[CSRIndex]; - } - - //printf("Wrote reg %d = %lx\n", FirstReg->RegAddress, FirstReg->RegValue); } - printf("!!!!!\n\n"); + InstructionData->PC = PC; + InstructionData->insn = insn; + InstructionData->Mcycle = Mcycle; + InstructionData->Minstret = Minstret; + InstructionData->Trap = Trap; + InstructionData->PrivilegeMode = PrivilegeMode; + InstructionData->GPREn = GPRWen; + InstructionData->FPREn = FPRWen; + InstructionData->CSRCount = CSRCount; + InstructionData->GPRReg = GPRReg; + InstructionData->GPRValue = GPRData; + InstructionData->FPRReg = FPRReg; + InstructionData->FPRValue = FPRData; + for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ + InstructionData->CSRWen[CSRIndex] = CSRWen[CSRIndex]; + InstructionData->CSRReg[CSRIndex] = CSRReg[CSRIndex]; + InstructionData->CSRValue[CSRIndex] = CSRValue[CSRIndex]; + } } void PrintInstructionData(RequiredRVVI_t *InstructionData){ int CSRIndex; - printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx, GPRWen = %hhx, FPRWen = %hhx, CSRCount == %hx\n", - InstructionData->PC, InstructionData->insn, InstructionData->Mcycle, InstructionData->Minstret, InstructionData->Trap, InstructionData->PrivilegeMode, InstructionData->GPREn, InstructionData->FPREn, InstructionData->CSRCount); + printf("PC = %lx, insn = %x, Mcycle = %lx, Minstret = %lx, Trap = %hhx, PrivilegeMode = %hhx", + InstructionData->PC, InstructionData->insn, InstructionData->Mcycle, InstructionData->Minstret, InstructionData->Trap, InstructionData->PrivilegeMode); if(InstructionData->GPREn){ - + printf(", GPR[%d] = %lx", InstructionData->GPRReg, InstructionData->GPRValue); + } + if(InstructionData->FPREn){ + printf(", FPR[%d] = %lx", InstructionData->FPRReg, InstructionData->FPRValue); } for(CSRIndex = 0; CSRIndex < 3; CSRIndex++){ if(InstructionData->CSRWen[CSRIndex]){ - printf("Wrote CSR %x with value %lx\n", InstructionData->CSRReg[CSRIndex], InstructionData->CSRValue[CSRIndex]); + printf(", CSR[%x] = %lx", InstructionData->CSRReg[CSRIndex], InstructionData->CSRValue[CSRIndex]); } } + printf("\n"); } void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 8a6b08f47..0efca4f53 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1134,7 +1134,7 @@ module fpgaTop packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); - eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), + eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), .rx_axis_tlast(), .rx_axis_tuser(), From 47523c97acc430a6636050abfe8c9ffeecf792d9 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Thu, 13 Jun 2024 15:46:54 -0700 Subject: [PATCH 041/163] Getting closer to figuring out the lost ethernet frame bugs. --- fpga/rvvidaemon/Makefile | 2 +- fpga/src/fpgaTopArtyA7.sv | 8 ++++---- src/rvvi/mii_phy_if.sv | 4 ++-- src/rvvi/packetizer.sv | 31 ++++++++++++++++++++++++------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/fpga/rvvidaemon/Makefile b/fpga/rvvidaemon/Makefile index c1d1d5a1c..d529a1212 100644 --- a/fpga/rvvidaemon/Makefile +++ b/fpga/rvvidaemon/Makefile @@ -1,7 +1,7 @@ all: rvvidaemon rvvidaemon: rvvidaemon.o - gcc $^ -o rvvidaemon + gcc $^ /opt/riscv/ImperasDV-OpenHW/Imperas/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model.so -o rvvidaemon %.o:%.c gcc -c $^ -o $@ diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 0efca4f53..51de188db 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1122,9 +1122,9 @@ module fpgaTop rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .valid, .rvvi); // axi 4 write data channel - logic [31:0] RvviAxiWdata; - logic [3:0] RvviAxiWstrb; - logic RvviAxiWlast; +(* mark_debug = "true" *) logic [31:0] RvviAxiWdata; +(* mark_debug = "true" *) logic [3:0] RvviAxiWstrb; +(* mark_debug = "true" *) logic RvviAxiWlast; (* mark_debug = "true" *) logic RvviAxiWvalid; (* mark_debug = "true" *) logic RvviAxiWready; @@ -1134,7 +1134,7 @@ module fpgaTop packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); - eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), + eth_mac_mii_fifo #(.TARGET("GENERIC"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), .rx_axis_tlast(), .rx_axis_tuser(), diff --git a/src/rvvi/mii_phy_if.sv b/src/rvvi/mii_phy_if.sv index 340d7ad24..f3857ed06 100644 --- a/src/rvvi/mii_phy_if.sv +++ b/src/rvvi/mii_phy_if.sv @@ -53,8 +53,8 @@ module mii_phy_if # output wire mac_mii_rx_er, output wire mac_mii_tx_clk, output wire mac_mii_tx_rst, - input wire [3:0] mac_mii_txd, - input wire mac_mii_tx_en, +(* mark_debug = "true" *) input wire [3:0] mac_mii_txd, +(* mark_debug = "true" *) input wire mac_mii_tx_en, input wire mac_mii_tx_er, /* diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 5b16615a6..f2c80d928 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -59,23 +59,32 @@ module packetizer import cvw::*; #(parameter cvw_t P, logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvviDelay; - typedef enum {STATE_RDY, STATE_WAIT, STATE_TRANS, STATE_TRANS_DONE} statetype; - statetype CurrState, NextState; + typedef enum {STATE_RST, STATE_COUNT, STATE_RDY, STATE_WAIT, STATE_TRANS, STATE_TRANS_INSERT_DELAY} statetype; +(* mark_debug = "true" *) statetype CurrState, NextState; + + logic [31:0] RstCount; + logic RstCountRst, RstCountEn, CountFlag, DelayFlag; + always_ff @(posedge m_axi_aclk) begin - if(~m_axi_aresetn) CurrState <= STATE_RDY; + if(~m_axi_aresetn) CurrState <= STATE_RST; else CurrState <= NextState; end always_comb begin case(CurrState) + STATE_RST: NextState = STATE_COUNT; + STATE_COUNT: if (CountFlag) NextState = STATE_RDY; + else NextState = STATE_COUNT; STATE_RDY: if (TransReady & valid) NextState = STATE_TRANS; else if(~TransReady & valid) NextState = STATE_WAIT; else NextState = STATE_RDY; - STATE_WAIT: if(TransReady) NextState = STATE_TRANS; - else NextState = STATE_WAIT; - STATE_TRANS: if(BurstDone) NextState = STATE_RDY; - else NextState = STATE_TRANS; + STATE_WAIT: if(TransReady) NextState = STATE_TRANS; + else NextState = STATE_WAIT; + STATE_TRANS: if(BurstDone) NextState = STATE_TRANS_INSERT_DELAY; + else NextState = STATE_TRANS; + STATE_TRANS_INSERT_DELAY: if(DelayFlag) NextState = STATE_RDY; + else NextState = STATE_TRANS_INSERT_DELAY; default: NextState = STATE_RDY; endcase end @@ -84,6 +93,14 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign TransReady = RvviAxiWready; assign WordCountEnable = (CurrState == STATE_RDY & valid) | (CurrState == STATE_TRANS & TransReady); assign WordCountReset = CurrState == STATE_RDY; + assign RstCountEn = CurrState == STATE_COUNT | CurrState == STATE_TRANS_INSERT_DELAY; + assign RstCountRst = CurrState == STATE_RST | CurrState == STATE_TRANS; + + // have to count at least 250 ms after reset pulled to wait for the phy to actually be ready + // at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000. + counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); + assign CountFlag = RstCount == 32'd100000000; + assign DelayFlag = RstCount == 32'd48; flopenr #(187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)) rvvireg(m_axi_aclk, ~m_axi_aresetn, valid, rvvi, rvviDelay); From 82b54c0887669e11aedb79605807245b72808bcf Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Mon, 17 Jun 2024 09:15:59 -0700 Subject: [PATCH 042/163] Got IDV properly initalized. --- fpga/rvvidaemon/rvvidaemon.c | 51 ++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 54240e72b..7a33a00b5 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -42,6 +42,7 @@ #include <net/if.h> #include <netinet/ether.h> #include "rvviApi.h" // *** bug fix me when this file gets included into the correct directory. +#include "idv/idv.h" #define DEST_MAC0 0x43 @@ -140,13 +141,53 @@ int main(int argc, char **argv){ } printf("Here 4\n"); - /* if(!rvviVersionCheck(RVVI_API_VERSION)){ */ - /* printf("Bad RVVI_API_VERSION\n"); */ - /* } */ + if(!rvviVersionCheck(RVVI_API_VERSION)){ + printf("Bad RVVI_API_VERSION\n"); + } - //rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); + rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); + rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME,"riscv"); + rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC"); + rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56); + rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6); - //rvviRefInit(NULL); + // eventually we want to put the elffiles here + rvviRefInit(NULL); + rvviRefPcSet(0, 0x1000); + + // Volatile CSRs + rvviRefCsrSetVolatile(0, 0xC00); // CYCLE + rvviRefCsrSetVolatile(0, 0xB00); // MCYCLE + rvviRefCsrSetVolatile(0, 0xC02); // INSTRET + rvviRefCsrSetVolatile(0, 0xB02); // MINSTRET + rvviRefCsrSetVolatile(0, 0xC01); // TIME + + int iter; + for (iter = 0xC03; iter <= 0xC1F; iter++) { + rvviRefCsrSetVolatile(0, iter); // HPMCOUNTERx + } + // Machine MHPMCOUNTER3 - MHPMCOUNTER31 + for (iter = 0xB03; iter <= 0xB1F; iter++) { + rvviRefCsrSetVolatile(0, iter); // MHPMCOUNTERx + } + // cannot predict this register due to latency between + // pending and taken + rvviRefCsrSetVolatile(0, 0x344); // MIP + rvviRefCsrSetVolatile(0, 0x144); // SIP + + // set bootrom and bootram as volatile memory + rvviRefMemorySetVolatile(0x1000, 0x1FFF); + rvviRefMemorySetVolatile(0x2000, 0x2FFF); + + // Privileges for PMA are set in the imperas.ic + // volatile (IO) regions are defined here + // only real ROM/RAM areas are BOOTROM and UNCORE_RAM + rvviRefMemorySetVolatile(0x2000000, 0x2000000 + 0xFFFF); + rvviRefMemorySetVolatile(0x10060000, 0x10060000 + 0xFF); + rvviRefMemorySetVolatile(0x10000000, 0x10000000 + 0x7); + rvviRefMemorySetVolatile(0x0C000000, 0x0C000000 + 0x03FFFFFF); + rvviRefMemorySetVolatile(0x00013000, 0x00013000 + 0x7F); + rvviRefMemorySetVolatile(0x10040000, 0x10040000 + 0xFFF); while(1) { //printf("listener: Waiting to recvfrom...\n"); From cccb40e4b50ba97eea872461892fdeeac40648fa Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Mon, 17 Jun 2024 09:16:24 -0700 Subject: [PATCH 043/163] Got the tracer not overrunning ethernet buffers so frames are not being dropped. --- src/rvvi/packetizer.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index f2c80d928..85e56beb1 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -100,7 +100,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, // at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000. counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); assign CountFlag = RstCount == 32'd100000000; - assign DelayFlag = RstCount == 32'd48; + assign DelayFlag = RstCount == 32'd200; flopenr #(187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)) rvvireg(m_axi_aclk, ~m_axi_aresetn, valid, rvvi, rvviDelay); From 598770da518509f56131cb9f3141125777b26125 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Mon, 17 Jun 2024 12:37:10 -0700 Subject: [PATCH 044/163] Getting much closer to a working version. --- fpga/rvvidaemon/Makefile | 4 ++-- fpga/rvvidaemon/rvvidaemon.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/fpga/rvvidaemon/Makefile b/fpga/rvvidaemon/Makefile index d529a1212..4f048302d 100644 --- a/fpga/rvvidaemon/Makefile +++ b/fpga/rvvidaemon/Makefile @@ -1,10 +1,10 @@ all: rvvidaemon rvvidaemon: rvvidaemon.o - gcc $^ /opt/riscv/ImperasDV-OpenHW/Imperas/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model.so -o rvvidaemon + gcc $^ /opt/riscv/ImperasDV-OpenHW/Imperas/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model.so -o rvvidaemon %.o:%.c - gcc -c $^ -o $@ + gcc -I/opt/riscv/ImperasDV-OpenHW/Imperas/ImpProprietary/include/host -c $^ -o $@ clean: rm *.o rvvidaemon diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 7a33a00b5..bf875c771 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -95,6 +95,9 @@ typedef struct { void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData); void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); void PrintInstructionData(RequiredRVVI_t *InstructionData); +void ProcessRvviAll(RequiredRVVI_t *InstructionData); +void set_gpr(int hart, int reg, uint64_t value); +void set_fpr(int hart, int reg, uint64_t value); int main(int argc, char **argv){ @@ -207,6 +210,9 @@ int main(int argc, char **argv){ uint32_t insn; RequiredRVVI_t InstructionData; DecodeRVVI(buf + headerbytes, payloadbytes, &InstructionData); + // now let's drive IDV + // start simple just drive and compare PC. + ProcessRvviAll(&InstructionData); PrintInstructionData(&InstructionData); } } @@ -218,6 +224,28 @@ int main(int argc, char **argv){ return 0; } +void ProcessRvviAll(RequiredRVVI_t *InstructionData){ + long int found; + uint64_t time = InstructionData->Mcycle; + uint8_t trap = InstructionData->Trap; + uint64_t order = InstructionData->Minstret; + + if(InstructionData->GPREn) set_gpr(0, InstructionData->GPRReg, InstructionData->GPRValue); + if(InstructionData->FPREn) set_fpr(0, InstructionData->FPRReg, InstructionData->FPRValue); + // *** set is for nets like interrupts come back to this. + //found = rvviRefNetIndexGet("pc_rdata"); + //rvviRefNetSet(found, InstructionData->PC, time); + +} + +void set_gpr(int hart, int reg, uint64_t value){ + rvviDutGprSet(hart, reg, value); +} + +void set_fpr(int hart, int reg, uint64_t value){ + rvviDutFprSet(hart, reg, value); +} + void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData){ // you know this actually easiser in assembly. :( uint8_t buf2[BUF_SIZ], buf3[BUF_SIZ]; From 93829ce509ac9204efb5cb52af5248b0c1a3f84d Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Mon, 17 Jun 2024 13:41:40 -0700 Subject: [PATCH 045/163] Success! We have some instructions comparing across the FPGA and IDV! However I'm still losing ethernet frames. --- fpga/rvvidaemon/rvvidaemon.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index bf875c771..074ffa21c 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -98,6 +98,7 @@ void PrintInstructionData(RequiredRVVI_t *InstructionData); void ProcessRvviAll(RequiredRVVI_t *InstructionData); void set_gpr(int hart, int reg, uint64_t value); void set_fpr(int hart, int reg, uint64_t value); +void state_compare(int hart, uint64_t Minstret); int main(int argc, char **argv){ @@ -232,12 +233,46 @@ void ProcessRvviAll(RequiredRVVI_t *InstructionData){ if(InstructionData->GPREn) set_gpr(0, InstructionData->GPRReg, InstructionData->GPRValue); if(InstructionData->FPREn) set_fpr(0, InstructionData->FPRReg, InstructionData->FPRValue); + + if (trap) { + rvviDutTrap(0, InstructionData->PC, InstructionData->insn); + } else { + rvviDutRetire(0, InstructionData->PC, InstructionData->insn, 0); + } + + if(!trap) state_compare(0, InstructionData->Minstret); + // *** set is for nets like interrupts come back to this. //found = rvviRefNetIndexGet("pc_rdata"); //rvviRefNetSet(found, InstructionData->PC, time); } +void state_compare(int hart, uint64_t Minstret){ + uint8_t result = 1; + uint8_t stepOk = 0; + char buf[80]; + rvviDutCycleCountSet(Minstret); + if(rvviRefEventStep(hart) != 0) { + stepOk = 1; + result &= rvviRefPcCompare(hart); + result &= rvviRefInsBinCompare(hart); + result &= rvviRefGprsCompare(hart); + result &= rvviRefFprsCompare(hart); + //result &= rvviRefCsrCompare(hart); + } else { + result = 0; + } + + if (result == 0) { + sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); + idvMsgError(buf); + + //if (ON_MISMATCH_DUMP_STATE) dump_state(hart); + } + +} + void set_gpr(int hart, int reg, uint64_t value){ rvviDutGprSet(hart, reg, value); } From 00e0549c360dac4999d607376e1d512c164300bf Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 18 Jun 2024 07:44:19 -0700 Subject: [PATCH 046/163] I know what is wrong now. The ethernet device IP is not correctly generating the mii nibble stream. Some nibbles are dropped in each 4-byte word. The default input interface to the interface is 8-bit and I used 32-bit. I suspect there is a bug in the implementation for non-8-bit interfaces. --- src/rvvi/packetizer.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 85e56beb1..e2d8fc19c 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -100,7 +100,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, // at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000. counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); assign CountFlag = RstCount == 32'd100000000; - assign DelayFlag = RstCount == 32'd200; + //assign DelayFlag = RstCount == 32'd200; + assign DelayFlag = RstCount == 32'd0; flopenr #(187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)) rvvireg(m_axi_aclk, ~m_axi_aresetn, valid, rvvi, rvviDelay); From 2581ea0b748c23cd904f0d4463eaa4315cdec5f4 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 18 Jun 2024 16:48:49 -0700 Subject: [PATCH 047/163] Found the actual bug. Once the ethernet transmit fifo was full the rvvi packetizer was not correctly marking the end of the frame. First Last was held for too many cycles. Second it was assert on cycles when Valid was not high. Simulation reproduced the FPGA corrupted frames and then with the fix showed working frames. --- src/rvvi/packetizer.sv | 5 ++-- src/rvvi/rvvisynth.sv | 63 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index e2d8fc19c..8ccec184d 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -81,7 +81,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, else NextState = STATE_RDY; STATE_WAIT: if(TransReady) NextState = STATE_TRANS; else NextState = STATE_WAIT; - STATE_TRANS: if(BurstDone) NextState = STATE_TRANS_INSERT_DELAY; + STATE_TRANS: if(BurstDone & TransReady) NextState = STATE_TRANS_INSERT_DELAY; else NextState = STATE_TRANS; STATE_TRANS_INSERT_DELAY: if(DelayFlag) NextState = STATE_RDY; else NextState = STATE_TRANS_INSERT_DELAY; @@ -100,6 +100,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, // at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000. counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); assign CountFlag = RstCount == 32'd100000000; + //assign CountFlag = RstCount == 32'd10; //assign DelayFlag = RstCount == 32'd200; assign DelayFlag = RstCount == 32'd0; @@ -128,7 +129,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign RvviAxiWdata = TotalFrameWords[WordCount]; assign RvviAxiWstrb = '1; - assign RvviAxiWlast = BurstDone; + assign RvviAxiWlast = BurstDone & (CurrState == STATE_TRANS); assign RvviAxiWvalid = (CurrState == STATE_TRANS); endmodule diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index df96ba446..16b214e18 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -27,6 +27,8 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// +`define FPGA 1 + module rvvisynth import cvw::*; #(parameter cvw_t P, parameter integer MAX_CSRS)( input logic clk, reset, @@ -62,6 +64,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. + if (`FPGA) begin assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; @@ -120,6 +123,66 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + end else begin // if (`FPGA) + assign StallE = dut.core.StallE; + assign StallM = dut.core.StallM; + assign StallW = dut.core.StallW; + assign FlushE = dut.core.FlushE; + assign FlushM = dut.core.FlushM; + assign FlushW = dut.core.FlushW; + assign InstrValidM = dut.core.ieu.InstrValidM; + assign InstrRawD = dut.core.ifu.InstrRawD; + assign PCM = dut.core.ifu.PCM; + assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = dut.core.TrapM; + assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = dut.core.ieu.dp.regf.a3; + assign GPRWen = dut.core.ieu.dp.regf.we3; + assign GPRValue = dut.core.ieu.dp.regf.wd3; + assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + end // assign XLENZeros = '0; From 1c6ebb86a313aaae24ce9b09090cdfbc7d0dd9d3 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Thu, 20 Jun 2024 12:54:12 -0700 Subject: [PATCH 048/163] Added some debug code to count frames sent to the ethernet mac and frames sent to the phy. Removed the external reset of the phy and now it always reliably starts in the same way. The first 0x117 frames are always captured. --- fpga/rvvidaemon/rvvidaemon.c | 2 +- fpga/src/fpgaTopArtyA7.sv | 5 +++-- src/rvvi/packetizer.sv | 10 +++++++--- testbench/testbench.sv | 9 ++++++++- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 074ffa21c..8a714dee0 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -213,8 +213,8 @@ int main(int argc, char **argv){ DecodeRVVI(buf + headerbytes, payloadbytes, &InstructionData); // now let's drive IDV // start simple just drive and compare PC. - ProcessRvviAll(&InstructionData); PrintInstructionData(&InstructionData); + ProcessRvviAll(&InstructionData); } } diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 51de188db..f495e2568 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1134,7 +1134,7 @@ module fpgaTop packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); - eth_mac_mii_fifo #(.TARGET("GENERIC"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), + eth_mac_mii_fifo #(.TARGET("XILINX"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), .rx_axis_tlast(), .rx_axis_tuser(), @@ -1155,7 +1155,8 @@ module fpgaTop .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) ); - assign phy_reset_n = ~bus_struct_reset; + //assign phy_reset_n = ~bus_struct_reset; + assign phy_reset_n = ~1'b0; endmodule diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 8ccec184d..e12e9cd7e 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -62,7 +62,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, typedef enum {STATE_RST, STATE_COUNT, STATE_RDY, STATE_WAIT, STATE_TRANS, STATE_TRANS_INSERT_DELAY} statetype; (* mark_debug = "true" *) statetype CurrState, NextState; - logic [31:0] RstCount; + logic [31:0] RstCount; +(* mark_debug = "true" *) logic [31:0] FrameCount; logic RstCountRst, RstCountEn, CountFlag, DelayFlag; @@ -101,8 +102,11 @@ module packetizer import cvw::*; #(parameter cvw_t P, counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); assign CountFlag = RstCount == 32'd100000000; //assign CountFlag = RstCount == 32'd10; - //assign DelayFlag = RstCount == 32'd200; - assign DelayFlag = RstCount == 32'd0; + assign DelayFlag = RstCount == 32'd200; + //assign DelayFlag = RstCount == 32'd0; + + counter #(32) framecounter(m_axi_aclk, ~m_axi_aresetn, (RvviAxiWready & RvviAxiWlast), FrameCount); + flopenr #(187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)) rvvireg(m_axi_aclk, ~m_axi_aresetn, valid, rvvi, rvviDelay); diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 399a5453d..098280423 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -633,7 +633,14 @@ module testbench; .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) ); - + + logic MiiTxEnDelay; + logic EthernetTXCounterEn; + logic [31:0] EthernetTXCount; + flopr #(1) txedgereg(clk, reset, mii_tx_en, MiiTxEnDelay); + assign EthernetTXCounterEn = ~mii_tx_en & MiiTxEnDelay; + counter #(32) ethernexttxcounter(clk, reset, EthernetTXCounterEn, EthernetTXCount); + end else begin assign RVVIStall = '0; end From 249d58244a3283236feed21ba21ad20f592201c5 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Thu, 20 Jun 2024 15:48:30 -0700 Subject: [PATCH 049/163] It's working!!!!!! --- fpga/rvvidaemon/rvviApi.h | 697 ++++++++++++++++++++++++++++++++++++++ src/rvvi/packetizer.sv | 2 +- 2 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 fpga/rvvidaemon/rvviApi.h diff --git a/fpga/rvvidaemon/rvviApi.h b/fpga/rvvidaemon/rvviApi.h new file mode 100644 index 000000000..d37286781 --- /dev/null +++ b/fpga/rvvidaemon/rvviApi.h @@ -0,0 +1,697 @@ +/* + * Copyright (c) 2005-2023 Imperas Software Ltd., www.imperas.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +/*! \file rvviApi.h + * \brief RVVI interface, C API header. +**/ + +#include <stdint.h> + +typedef uint32_t bool_t; + +#define RVVI_API_VERSION_MAJOR 1 +#define RVVI_API_VERSION_MINOR 34 +#define RVVI_TRUE 1 +#define RVVI_FALSE 0 +#define RVVI_INVALID_INDEX -1 +#define RVVI_MEMORY_PRIVILEGE_READ 1 +#define RVVI_MEMORY_PRIVILEGE_WRITE 2 +#define RVVI_MEMORY_PRIVILEGE_EXEC 4 +#define RVVI_API_VERSION ((RVVI_API_VERSION_MAJOR << 24) | RVVI_API_VERSION_MINOR) + +typedef enum { + RVVI_METRIC_RETIRES = 0, + RVVI_METRIC_TRAPS = 1, + RVVI_METRIC_MISMATCHES = 2, + RVVI_METRIC_COMPARISONS_PC = 3, + RVVI_METRIC_COMPARISONS_GPR = 4, + RVVI_METRIC_COMPARISONS_FPR = 5, + RVVI_METRIC_COMPARISONS_CSR = 6, + RVVI_METRIC_COMPARISONS_VR = 7, + RVVI_METRIC_COMPARISONS_INSBIN = 8, + RVVI_METRIC_CYCLES = 9, + RVVI_METRIC_ERRORS = 10, + RVVI_METRIC_WARNINGS = 11, + RVVI_METRIC_FATALS = 12, +} rvviMetricE; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Check the compiled RVVI API version. + * + * Makes sure the RVVI implementation linked with matches the versions defined in this header file. This should be called before any other RVVI API function. If this function returns RVVI_FALSE, no other RVVI API function should be called. + * + * \param version Should be set to RVVI_API_VERSION. + * + * \return RVVI_TRUE if versions matches otherwise RVVI_FALSE. +**/ +extern bool_t rvviVersionCheck( + uint32_t version); + +/*! \brief Initialize the DV reference model. + * + * \param programPath File path of the ELF file to be executed. This parameter can be NULL if required. + * + * \return RVVI_TRUE if the reference was initialized successfully else RVVI_FALSE. + * + * \note The reference model will begin execution from the entry point of the provided ELF file but can be overridden by the rvviRefPcSet() function. +**/ +extern bool_t rvviRefInit( + const char *programPath); + +/*! \brief Force the PC of the reference model to be particular value. + * + * \param hartId The hart to change the PC register of. + * \param address The address to change the PC register to. + * + * \return RVVI_TRUE on success else RVVI_FALSE. +**/ +extern bool_t rvviRefPcSet( + uint32_t hartId, + uint64_t address); + +/*! \brief Shutdown the reference module releasing any used resources. + * + * \return Returns RVVI_TRUE if shutdown was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefShutdown(void); + +/*! \brief Notify the reference that a CSR is considered volatile. + * + * \param hartId The hart that will have its CSR made volatile. + * \param csrIndex Index of the CSR register to be considered volatile (0x0 to 0xfff). + * + * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefCsrSetVolatile( + uint32_t hartId, + uint32_t csrIndex); + +/*! \brief Notify the reference that a memory region is volatile. + * + * \param addressLow Lower address of the volatile memory region + * \param addressHigh Upper address of the volatile memory region (inclusive) + * + * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefMemorySetVolatile( + uint64_t addressLow, + uint64_t addressHigh); + +/*! \brief Lookup a net on the reference model and return its index. + * + * \param name The net name to locate. + * + * \return Unique index for this net or RVVI_INVALID_INDEX if it was not found. + * + * \note Please consult the model datasheet for a list of valid net names. + * \note See also, rvviRefNetSet(). +**/ +extern uint64_t rvviRefNetIndexGet( + const char *name); + +/*! \brief Extract a byte from the reference models vector register. + * + * \param hartId The hart to extract the vector register byte from. + * \param vrIndex The vector register index (0 to 31). + * \param byteIndex The byte offset into the vector register (note 0 is LSB). + * + * \return Byte that has been extracted from the vector register. +**/ +extern uint8_t rvviRefVrGet( + uint32_t hartId, + uint32_t vrIndex, + uint32_t byteIndex); + +/*! \brief Notify RVVI that a byte in the DUTs vector register has changed. + * + * \param hartId The hart that has updated its vector register. + * \param vrIndex The vector register index (0 to 31). + * \param byteIndex The byte offset into the vector register (note 0 is LSB). + * \param data New byte value in the DUTs vector register. +**/ +extern void rvviDutVrSet( + uint32_t hartId, + uint32_t vrIndex, + uint32_t byteIndex, + uint8_t data); + +/*! \brief Notify RVVI that a DUT floating point register has been written to. + * + * \param hartId The hart that has updated its FPR. + * \param fprIndex The FPR index within the register file (0 to 31). + * \param value The value that has been written. +**/ +extern void rvviDutFprSet( + uint32_t hartId, + uint32_t fprIndex, + uint64_t value); + +/*! \brief Notify RVVI that a DUT GPR has been written to. + * + * \param hartId The hart that has updated its GPR. + * \param gprIndex The GPR index within the register file. + * \param value The value that has been written. +**/ +extern void rvviDutGprSet( + uint32_t hartId, + uint32_t gprIndex, + uint64_t value); + +/*! \brief Notify RVVI that a DUT CSR has been written to. + * + * \param hartId The hart that has updated its CSR. + * \param csrIndex The CSR index (0x0 to 0xfff). + * \param value The value that has been written. +**/ +extern void rvviDutCsrSet( + uint32_t hartId, + uint32_t csrIndex, + uint64_t value); + +/*! \brief Place a net in a specific net group. + * + * \param netIndex The net index returned prior by rvviRefNetIndexGet(). + * \param group The group index to place this net into. +**/ +extern void rvviRefNetGroupSet( + uint64_t netIndex, + uint32_t group); + +/*! \brief Propagate a net change to the reference model. + * + * \param netIndex The net index returned prior by rvviRefNetIndexGet(). + * \param value The new value to set the net state to. + * \param when Time of arrival of this net, in simulation time. The `when` parameter may be measured in simulation time or cycles. It allows the RVVI-API to know which net changes have arrived at the same time. +**/ +extern void rvviRefNetSet( + uint64_t netIndex, + uint64_t value, + uint64_t when); + +/*! \brief Read the state of a net on the reference model. + * + * \param netIndex The net index returned prior by rvviRefNetIndexGet(). + * + * \return The value present on the specified net. +**/ +extern uint64_t rvviRefNetGet( + uint64_t netIndex); + +/*! \brief Notify the reference that a DUT instruction has retired. + * + * \param hartId The hart that has retired an instruction. + * \param dutPc The address of the instruction that has retired. + * \param dutInsBin The binary instruction representation. + * \param debugMode True if this instruction was executed in debug mode. +**/ +extern void rvviDutRetire( + uint32_t hartId, + uint64_t dutPc, + uint64_t dutInsBin, + bool_t debugMode); + +/*! \brief Notify the reference that the DUT received a trap. + * + * \param hartId The hart that has retired an instruction. + * \param dutPc The address of the instruction that has retired. + * \param dutInsBin The binary instruction representation. +**/ +extern void rvviDutTrap( + uint32_t hartId, + uint64_t dutPc, + uint64_t dutInsBin); + +/*! \brief Invalidate the reference models LR/SC reservation. + * + * \param hartId The hart of which the LR/SC reservation will be made invalid. +**/ +extern void rvviRefReservationInvalidate( + uint32_t hartId); + +/*! \brief Step the reference model until the next event. + * + * \param hartId The ID of the hart that is being stepped. + * + * \return Returns RVVI_TRUE if the step was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefEventStep( + uint32_t hartId); + +/*! \brief Compare all GPR register values between reference and DUT. + * + * \param hartId The ID of the hart that is being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefGprsCompare( + uint32_t hartId); + +/*! \brief Compare GPR registers that have been written to between the reference and DUT. This can be seen as a super set of the rvviRefGprsCompare function. This comparator will also flag differences in the set of registers that have been written to. + * + * \param hartId The ID of the hart that is being compared. + * \param ignoreX0 RVVI_TRUE to not compare writes to the x0 register, which may be treated as a special case, otherwise RVVI_FALSE. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefGprsCompareWritten( + uint32_t hartId, + bool_t ignoreX0); + +/*! \brief Compare retired instruction bytes between reference and DUT. + * + * \param hartId The ID of the hart that is being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefInsBinCompare( + uint32_t hartId); + +/*! \brief Compare program counter for the retired instructions between DUT and the the reference model. + * + * \param hartId The ID of the hart that is being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefPcCompare( + uint32_t hartId); + +/*! \brief Compare a CSR value between DUT and the the reference model. + * + * \param hartId The ID of the hart that is being compared. + * \param csrIndex The index of the CSR register being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefCsrCompare( + uint32_t hartId, + uint32_t csrIndex); + +/*! \brief Enable or disable comparison of a specific CSR during rvviRefCsrsCompare. + * + * \param hartId The ID of the hart that this should apply to. + * \param csrIndex The index of the CSR to enable or disable comparison of. + * \param enableState RVVI_TRUE to enable comparison or RVVI_FALSE to disable. +**/ +extern void rvviRefCsrCompareEnable( + uint32_t hartId, + uint32_t csrIndex, + bool_t enableState); + +/*! \brief Specify a bitmask to direct bit level CSR comparisons. + * + * \param hartId The ID of the hart that this should apply to. + * \param csrIndex The index of the CSR to control the comparison of. + * \param mask Bitmask to enable or disable bits during CSR compare operations. Bits set to 1 will be compared and 0 bits are ignored. +**/ +extern void rvviRefCsrCompareMask( + uint32_t hartId, + uint32_t csrIndex, + uint64_t mask); + +/*! \brief Compare all CSR values between DUT and the the reference model. + * + * This function will compare the value of all CSRs between the reference and the DUT. Note that specific CSRs can be removed from this comparison by using the rvviRefCsrCompareEnable function. + * + * \param hartId The ID of the hart that is being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefCsrsCompare( + uint32_t hartId); + +/*! \brief Compare all RVV vector register values between reference and DUT. + * + * \param hartId The ID of the hart that is being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefVrsCompare( + uint32_t hartId); + +/*! \brief Compare all floating point register values between reference and DUT. + * + * \param hartId The ID of the hart that is being compared. + * + * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. +**/ +extern bool_t rvviRefFprsCompare( + uint32_t hartId); + +/*! \brief Write to the GPR of a hart in the reference model. + * + * \param hartId The hart to write the GPR of. + * \param gprIndex Index of the GPR register to write. + * \param gprValue Value to write into the GPR register. +**/ +extern void rvviRefGprSet( + uint32_t hartId, + uint32_t gprIndex, + uint64_t gprValue); + +/*! \brief Read a GPR value from a hart in the reference model. + * + * \param hartId The hart to retrieve the GPR from. + * \param gprIndex Index of the GPR register to read. + * + * \return GPR value read from the reference model. +**/ +extern uint64_t rvviRefGprGet( + uint32_t hartId, + uint32_t gprIndex); + +/*! \brief Read a GPR written mask from the last rvviRefEventStep. + * + * Each bit index in the mask returned indicates if the corresponding GPR has been written to by the reference model. Ie, if bit 3 is set, then X3 was written to. + * + * \param hartId The hart to retrieve the GPR written mask from. + * + * \return The GPR written mask. +**/ +extern uint32_t rvviRefGprsWrittenGet( + uint32_t hartId); + +/*! \brief Return the program counter of a hart in the reference model. + * + * \param hartId The hart to retrieve the PC from. + * + * \return The program counter of the specified hart. +**/ +extern uint64_t rvviRefPcGet( + uint32_t hartId); + +/*! \brief Read a CSR value from a hart in the reference model. + * + * \param hartId The hart to retrieve the CSR from. + * \param csrIndex Index of the CSR register to read (0x0 to 0xfff). + * + * \return The CSR register value read from the specified hart. +**/ +extern uint64_t rvviRefCsrGet( + uint32_t hartId, + uint32_t csrIndex); + +/*! \brief Return the binary representation of the previously retired instruction. + * + * \param hartId The hart to retrieve the instruction from. + * + * \return The instruction bytes. +**/ +extern uint64_t rvviRefInsBinGet( + uint32_t hartId); + +/*! \brief Write the value of a floating point register for a hart in the reference model. + * + * \param hartId The hart to retrieve the FPR register from. + * \param fprIndex Index of the floating point register to read. + * \param fprValue The bit pattern to be written into the floating point register. +**/ +extern void rvviRefFprSet( + uint32_t hartId, + uint32_t fprIndex, + uint64_t fprValue); + +/*! \brief Read a floating point register value from a hart in the reference model. + * + * \param hartId The hart to retrieve the FPR register from. + * \param fprIndex Index of the floating point register to read. + * + * \return The FPR register value read from the specified hart. +**/ +extern uint64_t rvviRefFprGet( + uint32_t hartId, + uint32_t fprIndex); + +/*! \brief Notify RVVI that the DUT has been written to memory. + * + * \param hartId The hart that issued the data bus write. + * \param address The address the hart is writing to. + * \param value The value placed on the data bus. + * \param byteEnableMask The byte enable mask provided for this write. + * + * \note Bus writes larger than 64bits should be reported using multiple calls to this function. + * \note byteEnableMask bit 0 corresponds to address+0, bEnMask bit 1 corresponds to address+1, etc. +**/ +extern void rvviDutBusWrite( + uint32_t hartId, + uint64_t address, + uint64_t value, + uint64_t byteEnableMask); + +/*! \brief Write data to the reference models physical memory space. + * + * \param hartId The hart to write from the perspective of. + * \param address The address being written to. + * \param data The data byte being written into memory. + * \param size Size of the data being written in bytes (1 to 8). +**/ +extern void rvviRefMemoryWrite( + uint32_t hartId, + uint64_t address, + uint64_t data, + uint32_t size); + +/*! \brief Read data from the reference models physical memory space. + * + * \param hartId The hart to read from the perspective of. + * \param address The address being read from. + * \param size Size of the data being read in bytes (1 to 8). + * + * \return The data that has been read from reference memory. +**/ +extern uint64_t rvviRefMemoryRead( + uint32_t hartId, + uint64_t address, + uint32_t size); + +/*! \brief Disassemble an arbitrary instruction encoding. + * + * \param hartId Hart with the ISA we are disassembling for. + * \param address Address of the instruction in memory. + * \param insBin The raw instruction that should be disassembled. + * + * \return Null terminated string containing the disassembly. +**/ +extern const char *rvviDasmInsBin( + uint32_t hartId, + uint64_t address, + uint64_t insBin); + +/*! \brief Return the name of a CSR in the reference model. + * + * \param hartId Hart with the CSR we are looking up the name of. + * \param csrIndex The index of the CSR we are looking up (0x0 to 0xfff inclusive). + * + * \return Null terminated string containing the CSR name. +**/ +extern const char *rvviRefCsrName( + uint32_t hartId, + uint32_t csrIndex); + +/*! \brief Return the ABI name of a GPR in the reference model. + * + * \param hartId Hart with the GPR we are looking up the name of. + * \param gprIndex The index of the GPR we are looking up (0 to 31 inclusive). + * + * \return Null terminated string containing the GPR ABI name. +**/ +extern const char *rvviRefGprName( + uint32_t hartId, + uint32_t gprIndex); + +/*! \brief Check if a CSR is present in the reference model. + * + * \param hartId Hart with the CSR we are checking the presence of. + * \param csrIndex The index of the CSR we are checking for (0x0 to 0xfff inclusive). + * + * \return RVVI_TRUE if the CSR is present in the reference model else RVVI_FALSE. +**/ +extern bool_t rvviRefCsrPresent( + uint32_t hartId, + uint32_t csrIndex); + +/*! \brief Check if floating point registers are present in the reference model. + * + * \param hartId Hart Id we are checking for the presence of floating point registers. + * + * \return RVVI_TRUE if the floating point registers are present in the reference model else RVVI_FALSE. +**/ +extern bool_t rvviRefFprsPresent( + uint32_t hartId); + +/*! \brief Check if vector registers are present in the reference model. + * + * \param hartId Hart Id we are checking for the presence of vector registers. + * + * \return RVVI_TRUE if the vector registers are present in the reference model else RVVI_FALSE. +**/ +extern bool_t rvviRefVrsPresent( + uint32_t hartId); + +/*! \brief Return the name of a FPR in the reference model. + * + * \param hartId Hart with the FPR we are looking up the name of. + * \param fprIndex The index of the FPR we are looking up (0 to 31 inclusive). + * + * \return Null terminated string containing the FPR name. +**/ +extern const char *rvviRefFprName( + uint32_t hartId, + uint32_t fprIndex); + +/*! \brief Return the name of a vector register in the reference model. + * + * \param hartId Hart with the VR we are looking up the name of. + * \param vrIndex The index of the VR we are looking up (0 to 31 inclusive). + * + * \return Null terminated string containing the VR name. +**/ +extern const char *rvviRefVrName( + uint32_t hartId, + uint32_t vrIndex); + +/*! \brief Return a string detailing the last RVVI-API error. + * + * \return The error string or an empty string if no error has occurred. +**/ +extern const char *rvviErrorGet(void); + +/*! \brief Query a verification metric from the reference model. + * + * \param metric An enumeration identifying the metric to query and return. + * + * \return The scalar quantity that has been queried. +**/ +extern uint64_t rvviRefMetricGet( + rvviMetricE metric); + +/*! \brief Set the value of a CSR in the reference model. + * + * \param hartId The hart which we are modifying the CSR of. + * \param csrIndex The index of the CSR we are modifying (0x0 to 0xfff inclusive). + * \param value The value to write into the CSR. +**/ +extern void rvviRefCsrSet( + uint32_t hartId, + uint32_t csrIndex, + uint64_t value); + +/*! \brief Dump the current register state of a hart in the reference model. + * + * \param hartId The hart which we should dump the register state of. +**/ +extern void rvviRefStateDump( + uint32_t hartId); + +/*! \brief Load an additional program into the address space of the processor. + * + * \param programPath File path of the ELF file to be loaded into memory. + * + * \return RVVI_TRUE if the program was loaded successfully otherwise RVVI_FALSE +**/ +extern bool_t rvviRefProgramLoad( + const char *programPath); + +/*! \brief Apply fine grain control over a CSRs volatility in the reference model. + * + * \param hartId The hart that will have its CSR volatility adjusted. + * \param csrIndex Index of the CSR register to have its volatility modified (0x0 to 0xfff). + * \param csrMask Bitmask specifying volatility, set bits will be treated as volatile, clear bits are not + * + * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefCsrSetVolatileMask( + uint32_t hartId, + uint32_t csrIndex, + uint64_t csrMask); + +/*! \brief Pass the current testbench cycle count to the RVVI implementation. + * + * \param cycleCount The current cycle count of the DUT. This value is directly related to, and must be consistent with, the `when` parameter for rvviRefNetSet(). +**/ +extern void rvviDutCycleCountSet( + uint64_t cycleCount); + +/*! \brief Pass a vendor specific integer configuration parameter to the RVVI implementation. + * + * \param configParam The configuration option that is to have its associated value set. This is vendor specific and not defined as part of the RVVI-API. + * \param value An integer containing the data that should be passed to the configuration option. + * + * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefConfigSetInt( + uint64_t configParam, + uint64_t value); + +/*! \brief Pass a vendor specific string configuration parameter to the RVVI implementation. + * + * \param configParam The configuration option that is to have its associated value set. This is vendor specific and not defined as part of the RVVI-API. + * \param value A string containing the data that should be passed to the configuration option. + * + * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefConfigSetString( + uint64_t configParam, + const char *value); + +/*! \brief Given the name of a CSR, its unique index/address will be returned. + * + * \param hartId HartId of the hart containing the CSR we are looking up the index of. + * \param csrName The CSR name for which the CSR index should be retrieved. + * + * \return Returns the CSR index if the operation was successful else RVVI_INVALID_INDEX. +**/ +extern uint32_t rvviRefCsrIndex( + uint32_t hartId, + const char *csrName); + +/*! \brief Set the privilege mode for a region of the address space. + * + * \param addrLo Lower address defining the memory region. + * \param addrHi Upper address defining the memory region (inclusive). + * \param access Access flags for this memory region; a combination of RVVI_PRIV_... flags or 0. + * + * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. +**/ +extern bool_t rvviRefMemorySetPrivilege( + uint64_t addrLo, + uint64_t addrHi, + uint32_t access); + +/*! \brief Update a byte in one of the reference models vector registers. + * + * \param hartId The hart that should have its vector register updated. + * \param vrIndex The vector register index (0 to 31). + * \param byteIndex The byte offset into the vector register (note 0 is LSB). + * \param data New byte value to be written into the vector register. +**/ +extern void rvviRefVrSet( + uint32_t hartId, + uint32_t vrIndex, + uint32_t byteIndex, + uint8_t data); + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index e12e9cd7e..1599c28a9 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -102,7 +102,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); assign CountFlag = RstCount == 32'd100000000; //assign CountFlag = RstCount == 32'd10; - assign DelayFlag = RstCount == 32'd200; + assign DelayFlag = RstCount == 32'd800; //assign DelayFlag = RstCount == 32'd0; counter #(32) framecounter(m_axi_aclk, ~m_axi_aresetn, (RvviAxiWready & RvviAxiWlast), FrameCount); From fa26c9a8b5382d2d94b8e17c15e54d7b3212710f Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 25 Jun 2024 13:07:46 -0700 Subject: [PATCH 050/163] Added pipe to vivado to create ila trigger from rvvidaemon. --- fpga/rvvidaemon/rvvidaemon.c | 46 +++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 8a714dee0..f6019dd19 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -66,6 +66,7 @@ //#define ETHER_TYPE 0x0000 // The type defined in packetizer.sv #define DEFAULT_IF "eno1" +FILE *VivadoPipeFP; typedef struct { uint64_t PC; @@ -95,10 +96,10 @@ typedef struct { void DecodeRVVI(uint8_t *payload, ssize_t payloadsize, RequiredRVVI_t *InstructionData); void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length); void PrintInstructionData(RequiredRVVI_t *InstructionData); -void ProcessRvviAll(RequiredRVVI_t *InstructionData); +int ProcessRvviAll(RequiredRVVI_t *InstructionData); void set_gpr(int hart, int reg, uint64_t value); void set_fpr(int hart, int reg, uint64_t value); -void state_compare(int hart, uint64_t Minstret); +int state_compare(int hart, uint64_t Minstret); int main(int argc, char **argv){ @@ -108,6 +109,24 @@ int main(int argc, char **argv){ return -1; } + // step 1 open a pipe to vivado + if (( VivadoPipeFP = popen("sort", "w")) == NULL){ + perror("popen"); + exit(1); + } + fputs("open_hw_manager\n", VivadoPipeFP); + fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); + fputs("current_hw_target [get_hw_targets */xilinx_tcf/Digilent/*]\n", VivadoPipeFP); + fputs("open_hw_target\n", VivadoPipeFP); + fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); + + // *** bug these need to made relative paths. + fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); + fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); + fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); + fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); + fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); + int sockfd; uint8_t buf[BUF_SIZ]; int sockopt; @@ -198,6 +217,7 @@ int main(int argc, char **argv){ numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL); headerbytes = (sizeof(struct ether_header)); payloadbytes = numbytes - headerbytes; + int result; //printf("listener: got frame %lu bytes\n", numbytes); //printf("payload size: %lu bytes\n", payloadbytes); if (eh->ether_dhost[0] == DEST_MAC0 && @@ -214,10 +234,14 @@ int main(int argc, char **argv){ // now let's drive IDV // start simple just drive and compare PC. PrintInstructionData(&InstructionData); - ProcessRvviAll(&InstructionData); + result = ProcessRvviAll(&InstructionData); + if(result == -1) break; } } + printf("Simulation halted due to mismatch\n"); + + pclose(VivadoPipeFP); close(sockfd); @@ -225,12 +249,14 @@ int main(int argc, char **argv){ return 0; } -void ProcessRvviAll(RequiredRVVI_t *InstructionData){ +int ProcessRvviAll(RequiredRVVI_t *InstructionData){ long int found; uint64_t time = InstructionData->Mcycle; uint8_t trap = InstructionData->Trap; uint64_t order = InstructionData->Minstret; + int result; + result = 0; if(InstructionData->GPREn) set_gpr(0, InstructionData->GPRReg, InstructionData->GPRValue); if(InstructionData->FPREn) set_fpr(0, InstructionData->FPRReg, InstructionData->FPRValue); @@ -240,15 +266,15 @@ void ProcessRvviAll(RequiredRVVI_t *InstructionData){ rvviDutRetire(0, InstructionData->PC, InstructionData->insn, 0); } - if(!trap) state_compare(0, InstructionData->Minstret); - + if(!trap) result = state_compare(0, InstructionData->Minstret); // *** set is for nets like interrupts come back to this. //found = rvviRefNetIndexGet("pc_rdata"); //rvviRefNetSet(found, InstructionData->PC, time); + return result; } -void state_compare(int hart, uint64_t Minstret){ +int state_compare(int hart, uint64_t Minstret){ uint8_t result = 1; uint8_t stepOk = 0; char buf[80]; @@ -267,7 +293,11 @@ void state_compare(int hart, uint64_t Minstret){ if (result == 0) { sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); idvMsgError(buf); - + fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); + fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); + fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); + fputs("write_hw_ila_data my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); + return -1; //if (ON_MISMATCH_DUMP_STATE) dump_state(hart); } From 74189e1e4b5c7633a5a29a4dad1198118bcc382a Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 25 Jun 2024 17:04:14 -0700 Subject: [PATCH 051/163] Have vivado triggering the ILA after the mismatch but the latency is way too long. --- fpga/rvvidaemon/rvvidaemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index f6019dd19..b2ccc2b63 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -110,7 +110,7 @@ int main(int argc, char **argv){ } // step 1 open a pipe to vivado - if (( VivadoPipeFP = popen("sort", "w")) == NULL){ + if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ perror("popen"); exit(1); } From 612a281f62507bedd5b61f5f4ce24aa644cfd99c Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 26 Jun 2024 11:05:31 -0700 Subject: [PATCH 052/163] Added module to receive ethernet frame and trigger the ila. --- fpga/constraints/small-debug.xdc | 35 ++++++------ fpga/src/fpgaTopArtyA7.sv | 12 ++++- src/rvvi/triggergen.sv | 92 ++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 19 deletions(-) create mode 100644 src/rvvi/triggergen.sv diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index 62fcbe545..c2daf9fe1 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -3,8 +3,8 @@ create_debug_core u_ila_0 ila -set_property C_DATA_DEPTH 1024 [get_debug_cores u_ila_0] -set_property C_TRIGIN_EN false [get_debug_cores u_ila_0] +set_property C_DATA_DEPTH 8192 [get_debug_cores u_ila_0] +set_property C_TRIGIN_EN true [get_debug_cores u_ila_0] set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0] set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] @@ -19,14 +19,14 @@ set_property ALL_PROBE_SAME_MU_CNT 4 [get_debug_cores u_ila_0 ] endgroup connect_debug_port u_ila_0/clk [get_nets CPUCLK] -set_property port_width 64 [get_debug_ports u_ila_0/probe0] +set_property port_width 32 [get_debug_ports u_ila_0/probe0] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] -connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] +connect_debug_port u_ila_0/probe0 [get_nets [list {RvviAxiWdata[0]} {RvviAxiWdata[1]} {RvviAxiWdata[2]} {RvviAxiWdata[3]} {RvviAxiWdata[4]} {RvviAxiWdata[5]} {RvviAxiWdata[6]} {RvviAxiWdata[7]} {RvviAxiWdata[8]} {RvviAxiWdata[9]} {RvviAxiWdata[10]} {RvviAxiWdata[11]} {RvviAxiWdata[12]} {RvviAxiWdata[13]} {RvviAxiWdata[14]} {RvviAxiWdata[15]} {RvviAxiWdata[16]} {RvviAxiWdata[17]} {RvviAxiWdata[18]} {RvviAxiWdata[19]} {RvviAxiWdata[20]} {RvviAxiWdata[21]} {RvviAxiWdata[22]} {RvviAxiWdata[23]} {RvviAxiWdata[24]} {RvviAxiWdata[25]} {RvviAxiWdata[26]} {RvviAxiWdata[27]} {RvviAxiWdata[28]} {RvviAxiWdata[29]} {RvviAxiWdata[30]} {RvviAxiWdata[31]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe1] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] -connect_debug_port u_ila_0/probe1 [get_nets [list wallypipelinedsoc/core/TrapM ]] +connect_debug_port u_ila_0/probe1 [get_nets [list RvviAxiWlast ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe2] @@ -34,29 +34,29 @@ set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] create_debug_port u_ila_0 probe -set_property port_width 32 [get_debug_ports u_ila_0/probe3] +set_property port_width 4 [get_debug_ports u_ila_0/probe3] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] -connect_debug_port u_ila_0/probe3 [get_nets [list {wallypipelinedsoc/core/InstrM[0]} {wallypipelinedsoc/core/InstrM[1]} {wallypipelinedsoc/core/InstrM[2]} {wallypipelinedsoc/core/InstrM[3]} {wallypipelinedsoc/core/InstrM[4]} {wallypipelinedsoc/core/InstrM[5]} {wallypipelinedsoc/core/InstrM[6]} {wallypipelinedsoc/core/InstrM[7]} {wallypipelinedsoc/core/InstrM[8]} {wallypipelinedsoc/core/InstrM[9]} {wallypipelinedsoc/core/InstrM[10]} {wallypipelinedsoc/core/InstrM[11]} {wallypipelinedsoc/core/InstrM[12]} {wallypipelinedsoc/core/InstrM[13]} {wallypipelinedsoc/core/InstrM[14]} {wallypipelinedsoc/core/InstrM[15]} {wallypipelinedsoc/core/InstrM[16]} {wallypipelinedsoc/core/InstrM[17]} {wallypipelinedsoc/core/InstrM[18]} {wallypipelinedsoc/core/InstrM[19]} {wallypipelinedsoc/core/InstrM[20]} {wallypipelinedsoc/core/InstrM[21]} {wallypipelinedsoc/core/InstrM[22]} {wallypipelinedsoc/core/InstrM[23]} {wallypipelinedsoc/core/InstrM[24]} {wallypipelinedsoc/core/InstrM[25]} {wallypipelinedsoc/core/InstrM[26]} {wallypipelinedsoc/core/InstrM[27]} {wallypipelinedsoc/core/InstrM[28]} {wallypipelinedsoc/core/InstrM[29]} {wallypipelinedsoc/core/InstrM[30]} {wallypipelinedsoc/core/InstrM[31]} ]] +connect_debug_port u_ila_0/probe3 [get_nets [list {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[0]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[1]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[2]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[3]} ]] create_debug_port u_ila_0 probe -set_property port_width 2 [get_debug_ports u_ila_0/probe4] +set_property port_width 4 [get_debug_ports u_ila_0/probe4] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] -connect_debug_port u_ila_0/probe4 [get_nets [list {wallypipelinedsoc/core/lsu/MemRWM[0]} {wallypipelinedsoc/core/lsu/MemRWM[1]} ]] +connect_debug_port u_ila_0/probe4 [get_nets [list {packetizer/CurrState[0]} {packetizer/CurrState[1]} {packetizer/CurrState[2]} {packetizer/CurrState[3]}]] create_debug_port u_ila_0 probe -set_property port_width 64 [get_debug_ports u_ila_0/probe5] +set_property port_width 1 [get_debug_ports u_ila_0/probe5] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] -connect_debug_port u_ila_0/probe5 [get_nets [list {wallypipelinedsoc/core/lsu/IEUAdrM[0]} {wallypipelinedsoc/core/lsu/IEUAdrM[1]} {wallypipelinedsoc/core/lsu/IEUAdrM[2]} {wallypipelinedsoc/core/lsu/IEUAdrM[3]} {wallypipelinedsoc/core/lsu/IEUAdrM[4]} {wallypipelinedsoc/core/lsu/IEUAdrM[5]} {wallypipelinedsoc/core/lsu/IEUAdrM[6]} {wallypipelinedsoc/core/lsu/IEUAdrM[7]} {wallypipelinedsoc/core/lsu/IEUAdrM[8]} {wallypipelinedsoc/core/lsu/IEUAdrM[9]} {wallypipelinedsoc/core/lsu/IEUAdrM[10]} {wallypipelinedsoc/core/lsu/IEUAdrM[11]} {wallypipelinedsoc/core/lsu/IEUAdrM[12]} {wallypipelinedsoc/core/lsu/IEUAdrM[13]} {wallypipelinedsoc/core/lsu/IEUAdrM[14]} {wallypipelinedsoc/core/lsu/IEUAdrM[15]} {wallypipelinedsoc/core/lsu/IEUAdrM[16]} {wallypipelinedsoc/core/lsu/IEUAdrM[17]} {wallypipelinedsoc/core/lsu/IEUAdrM[18]} {wallypipelinedsoc/core/lsu/IEUAdrM[19]} {wallypipelinedsoc/core/lsu/IEUAdrM[20]} {wallypipelinedsoc/core/lsu/IEUAdrM[21]} {wallypipelinedsoc/core/lsu/IEUAdrM[22]} {wallypipelinedsoc/core/lsu/IEUAdrM[23]} {wallypipelinedsoc/core/lsu/IEUAdrM[24]} {wallypipelinedsoc/core/lsu/IEUAdrM[25]} {wallypipelinedsoc/core/lsu/IEUAdrM[26]} {wallypipelinedsoc/core/lsu/IEUAdrM[27]} {wallypipelinedsoc/core/lsu/IEUAdrM[28]} {wallypipelinedsoc/core/lsu/IEUAdrM[29]} {wallypipelinedsoc/core/lsu/IEUAdrM[30]} {wallypipelinedsoc/core/lsu/IEUAdrM[31]} {wallypipelinedsoc/core/lsu/IEUAdrM[32]} {wallypipelinedsoc/core/lsu/IEUAdrM[33]} {wallypipelinedsoc/core/lsu/IEUAdrM[34]} {wallypipelinedsoc/core/lsu/IEUAdrM[35]} {wallypipelinedsoc/core/lsu/IEUAdrM[36]} {wallypipelinedsoc/core/lsu/IEUAdrM[37]} {wallypipelinedsoc/core/lsu/IEUAdrM[38]} {wallypipelinedsoc/core/lsu/IEUAdrM[39]} {wallypipelinedsoc/core/lsu/IEUAdrM[40]} {wallypipelinedsoc/core/lsu/IEUAdrM[41]} {wallypipelinedsoc/core/lsu/IEUAdrM[42]} {wallypipelinedsoc/core/lsu/IEUAdrM[43]} {wallypipelinedsoc/core/lsu/IEUAdrM[44]} {wallypipelinedsoc/core/lsu/IEUAdrM[45]} {wallypipelinedsoc/core/lsu/IEUAdrM[46]} {wallypipelinedsoc/core/lsu/IEUAdrM[47]} {wallypipelinedsoc/core/lsu/IEUAdrM[48]} {wallypipelinedsoc/core/lsu/IEUAdrM[49]} {wallypipelinedsoc/core/lsu/IEUAdrM[50]} {wallypipelinedsoc/core/lsu/IEUAdrM[51]} {wallypipelinedsoc/core/lsu/IEUAdrM[52]} {wallypipelinedsoc/core/lsu/IEUAdrM[53]} {wallypipelinedsoc/core/lsu/IEUAdrM[54]} {wallypipelinedsoc/core/lsu/IEUAdrM[55]} {wallypipelinedsoc/core/lsu/IEUAdrM[56]} {wallypipelinedsoc/core/lsu/IEUAdrM[57]} {wallypipelinedsoc/core/lsu/IEUAdrM[58]} {wallypipelinedsoc/core/lsu/IEUAdrM[59]} {wallypipelinedsoc/core/lsu/IEUAdrM[60]} {wallypipelinedsoc/core/lsu/IEUAdrM[61]} {wallypipelinedsoc/core/lsu/IEUAdrM[62]} {wallypipelinedsoc/core/lsu/IEUAdrM[63]} ]] +connect_debug_port u_ila_0/probe5 [get_nets [list {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_tx_en} ]] create_debug_port u_ila_0 probe set_property port_width 64 [get_debug_ports u_ila_0/probe6] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] -connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/lsu/ReadDataM[0]} {wallypipelinedsoc/core/lsu/ReadDataM[1]} {wallypipelinedsoc/core/lsu/ReadDataM[2]} {wallypipelinedsoc/core/lsu/ReadDataM[3]} {wallypipelinedsoc/core/lsu/ReadDataM[4]} {wallypipelinedsoc/core/lsu/ReadDataM[5]} {wallypipelinedsoc/core/lsu/ReadDataM[6]} {wallypipelinedsoc/core/lsu/ReadDataM[7]} {wallypipelinedsoc/core/lsu/ReadDataM[8]} {wallypipelinedsoc/core/lsu/ReadDataM[9]} {wallypipelinedsoc/core/lsu/ReadDataM[10]} {wallypipelinedsoc/core/lsu/ReadDataM[11]} {wallypipelinedsoc/core/lsu/ReadDataM[12]} {wallypipelinedsoc/core/lsu/ReadDataM[13]} {wallypipelinedsoc/core/lsu/ReadDataM[14]} {wallypipelinedsoc/core/lsu/ReadDataM[15]} {wallypipelinedsoc/core/lsu/ReadDataM[16]} {wallypipelinedsoc/core/lsu/ReadDataM[17]} {wallypipelinedsoc/core/lsu/ReadDataM[18]} {wallypipelinedsoc/core/lsu/ReadDataM[19]} {wallypipelinedsoc/core/lsu/ReadDataM[20]} {wallypipelinedsoc/core/lsu/ReadDataM[21]} {wallypipelinedsoc/core/lsu/ReadDataM[22]} {wallypipelinedsoc/core/lsu/ReadDataM[23]} {wallypipelinedsoc/core/lsu/ReadDataM[24]} {wallypipelinedsoc/core/lsu/ReadDataM[25]} {wallypipelinedsoc/core/lsu/ReadDataM[26]} {wallypipelinedsoc/core/lsu/ReadDataM[27]} {wallypipelinedsoc/core/lsu/ReadDataM[28]} {wallypipelinedsoc/core/lsu/ReadDataM[29]} {wallypipelinedsoc/core/lsu/ReadDataM[30]} {wallypipelinedsoc/core/lsu/ReadDataM[31]} {wallypipelinedsoc/core/lsu/ReadDataM[32]} {wallypipelinedsoc/core/lsu/ReadDataM[33]} {wallypipelinedsoc/core/lsu/ReadDataM[34]} {wallypipelinedsoc/core/lsu/ReadDataM[35]} {wallypipelinedsoc/core/lsu/ReadDataM[36]} {wallypipelinedsoc/core/lsu/ReadDataM[37]} {wallypipelinedsoc/core/lsu/ReadDataM[38]} {wallypipelinedsoc/core/lsu/ReadDataM[39]} {wallypipelinedsoc/core/lsu/ReadDataM[40]} {wallypipelinedsoc/core/lsu/ReadDataM[41]} {wallypipelinedsoc/core/lsu/ReadDataM[42]} {wallypipelinedsoc/core/lsu/ReadDataM[43]} {wallypipelinedsoc/core/lsu/ReadDataM[44]} {wallypipelinedsoc/core/lsu/ReadDataM[45]} {wallypipelinedsoc/core/lsu/ReadDataM[46]} {wallypipelinedsoc/core/lsu/ReadDataM[47]} {wallypipelinedsoc/core/lsu/ReadDataM[48]} {wallypipelinedsoc/core/lsu/ReadDataM[49]} {wallypipelinedsoc/core/lsu/ReadDataM[50]} {wallypipelinedsoc/core/lsu/ReadDataM[51]} {wallypipelinedsoc/core/lsu/ReadDataM[52]} {wallypipelinedsoc/core/lsu/ReadDataM[53]} {wallypipelinedsoc/core/lsu/ReadDataM[54]} {wallypipelinedsoc/core/lsu/ReadDataM[55]} {wallypipelinedsoc/core/lsu/ReadDataM[56]} {wallypipelinedsoc/core/lsu/ReadDataM[57]} {wallypipelinedsoc/core/lsu/ReadDataM[58]} {wallypipelinedsoc/core/lsu/ReadDataM[59]} {wallypipelinedsoc/core/lsu/ReadDataM[60]} {wallypipelinedsoc/core/lsu/ReadDataM[61]} {wallypipelinedsoc/core/lsu/ReadDataM[62]} {wallypipelinedsoc/core/lsu/ReadDataM[63]} ]] +connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] create_debug_port u_ila_0 probe -set_property port_width 64 [get_debug_ports u_ila_0/probe7] +set_property port_width 32 [get_debug_ports u_ila_0/probe7] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] -connect_debug_port u_ila_0/probe7 [get_nets [list {wallypipelinedsoc/core/lsu/WriteDataM[0]} {wallypipelinedsoc/core/lsu/WriteDataM[1]} {wallypipelinedsoc/core/lsu/WriteDataM[2]} {wallypipelinedsoc/core/lsu/WriteDataM[3]} {wallypipelinedsoc/core/lsu/WriteDataM[4]} {wallypipelinedsoc/core/lsu/WriteDataM[5]} {wallypipelinedsoc/core/lsu/WriteDataM[6]} {wallypipelinedsoc/core/lsu/WriteDataM[7]} {wallypipelinedsoc/core/lsu/WriteDataM[8]} {wallypipelinedsoc/core/lsu/WriteDataM[9]} {wallypipelinedsoc/core/lsu/WriteDataM[10]} {wallypipelinedsoc/core/lsu/WriteDataM[11]} {wallypipelinedsoc/core/lsu/WriteDataM[12]} {wallypipelinedsoc/core/lsu/WriteDataM[13]} {wallypipelinedsoc/core/lsu/WriteDataM[14]} {wallypipelinedsoc/core/lsu/WriteDataM[15]} {wallypipelinedsoc/core/lsu/WriteDataM[16]} {wallypipelinedsoc/core/lsu/WriteDataM[17]} {wallypipelinedsoc/core/lsu/WriteDataM[18]} {wallypipelinedsoc/core/lsu/WriteDataM[19]} {wallypipelinedsoc/core/lsu/WriteDataM[20]} {wallypipelinedsoc/core/lsu/WriteDataM[21]} {wallypipelinedsoc/core/lsu/WriteDataM[22]} {wallypipelinedsoc/core/lsu/WriteDataM[23]} {wallypipelinedsoc/core/lsu/WriteDataM[24]} {wallypipelinedsoc/core/lsu/WriteDataM[25]} {wallypipelinedsoc/core/lsu/WriteDataM[26]} {wallypipelinedsoc/core/lsu/WriteDataM[27]} {wallypipelinedsoc/core/lsu/WriteDataM[28]} {wallypipelinedsoc/core/lsu/WriteDataM[29]} {wallypipelinedsoc/core/lsu/WriteDataM[30]} {wallypipelinedsoc/core/lsu/WriteDataM[31]} {wallypipelinedsoc/core/lsu/WriteDataM[32]} {wallypipelinedsoc/core/lsu/WriteDataM[33]} {wallypipelinedsoc/core/lsu/WriteDataM[34]} {wallypipelinedsoc/core/lsu/WriteDataM[35]} {wallypipelinedsoc/core/lsu/WriteDataM[36]} {wallypipelinedsoc/core/lsu/WriteDataM[37]} {wallypipelinedsoc/core/lsu/WriteDataM[38]} {wallypipelinedsoc/core/lsu/WriteDataM[39]} {wallypipelinedsoc/core/lsu/WriteDataM[40]} {wallypipelinedsoc/core/lsu/WriteDataM[41]} {wallypipelinedsoc/core/lsu/WriteDataM[42]} {wallypipelinedsoc/core/lsu/WriteDataM[43]} {wallypipelinedsoc/core/lsu/WriteDataM[44]} {wallypipelinedsoc/core/lsu/WriteDataM[45]} {wallypipelinedsoc/core/lsu/WriteDataM[46]} {wallypipelinedsoc/core/lsu/WriteDataM[47]} {wallypipelinedsoc/core/lsu/WriteDataM[48]} {wallypipelinedsoc/core/lsu/WriteDataM[49]} {wallypipelinedsoc/core/lsu/WriteDataM[50]} {wallypipelinedsoc/core/lsu/WriteDataM[51]} {wallypipelinedsoc/core/lsu/WriteDataM[52]} {wallypipelinedsoc/core/lsu/WriteDataM[53]} {wallypipelinedsoc/core/lsu/WriteDataM[54]} {wallypipelinedsoc/core/lsu/WriteDataM[55]} {wallypipelinedsoc/core/lsu/WriteDataM[56]} {wallypipelinedsoc/core/lsu/WriteDataM[57]} {wallypipelinedsoc/core/lsu/WriteDataM[58]} {wallypipelinedsoc/core/lsu/WriteDataM[59]} {wallypipelinedsoc/core/lsu/WriteDataM[60]} {wallypipelinedsoc/core/lsu/WriteDataM[61]} {wallypipelinedsoc/core/lsu/WriteDataM[62]} {wallypipelinedsoc/core/lsu/WriteDataM[63]} ]] +connect_debug_port u_ila_0/probe7 [get_nets [list {packetizer/FrameCount[0]} {packetizer/FrameCount[1]} {packetizer/FrameCount[2]} {packetizer/FrameCount[3]} {packetizer/FrameCount[4]} {packetizer/FrameCount[5]} {packetizer/FrameCount[6]} {packetizer/FrameCount[7]} {packetizer/FrameCount[8]} {packetizer/FrameCount[9]} {packetizer/FrameCount[10]} {packetizer/FrameCount[11]} {packetizer/FrameCount[12]} {packetizer/FrameCount[13]} {packetizer/FrameCount[14]} {packetizer/FrameCount[15]} {packetizer/FrameCount[16]} {packetizer/FrameCount[17]} {packetizer/FrameCount[18]} {packetizer/FrameCount[19]} {packetizer/FrameCount[20]} {packetizer/FrameCount[21]} {packetizer/FrameCount[22]} {packetizer/FrameCount[23]} {packetizer/FrameCount[24]} {packetizer/FrameCount[25]} {packetizer/FrameCount[26]} {packetizer/FrameCount[27]} {packetizer/FrameCount[28]} {packetizer/FrameCount[29]} {packetizer/FrameCount[30]} {packetizer/FrameCount[31]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe8] @@ -78,11 +78,10 @@ set_property port_width 1 [get_debug_ports u_ila_0/probe11] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] connect_debug_port u_ila_0/probe11 [get_nets [list {RvviAxiWvalid}]] -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe12] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe12] -connect_debug_port u_ila_0/probe12 [get_nets [list {bus_struct_reset}]] # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] connect_debug_port dbg_hub/clk [get_nets CPUCLK] + +# connect the trig_in in of the ila to the +connect_debug_port u_ila_0/trig_in [get_nets [list {IlaTrigger}]] diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index f495e2568..811d32e4f 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1128,6 +1128,14 @@ module fpgaTop (* mark_debug = "true" *) logic RvviAxiWvalid; (* mark_debug = "true" *) logic RvviAxiWready; + logic RvviAxiRdata [31:0]; + logic RvviAxiRstrb [3:0]; + logic RvviAxiRlast; + logic RvviAxiRvalid; +(* mark_debug = "true" *) logic IlaTrigger; + + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; @@ -1139,7 +1147,6 @@ module fpgaTop .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), .rx_axis_tlast(), .rx_axis_tuser(), - // *** update these .mii_rx_clk(phy_rx_clk), .mii_rxd(phy_rxd), .mii_rx_dv(phy_rx_dv), @@ -1155,6 +1162,9 @@ module fpgaTop .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) ); + triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, + .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger) + //assign phy_reset_n = ~bus_struct_reset; assign phy_reset_n = ~1'b0; diff --git a/src/rvvi/triggergen.sv b/src/rvvi/triggergen.sv new file mode 100644 index 000000000..f8dc4ba8d --- /dev/null +++ b/src/rvvi/triggergen.sv @@ -0,0 +1,92 @@ +/////////////////////////////////////////// +// triggergen.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: June 26, 2024 +// Modified: June 26, 2024 +// +// Purpose: Scans for specific ethernet frame to generate an ila trigger. +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module triggergen import cvw::*; ( + input logic clk, reset, + input logic [31:0] RvviAxiRdata, + input logic [3:0] RvviAxiRstrb, + input logic RvviAxiRlast, + input logic RvviAxiRvalid, + output logic IlaTrigger); + + typedef enum {STATE_RST, STATE_COMPARE, STATE_MISMATCH, STATE_TRIGGER, STATE_TRIGGER_DONE} statetype; +(* mark_debug = "true" *) statetype CurrState, NextState; + + logic [31:0] mem [4:0]; + logic [2:0] Counter; + logic CounterEn, CounterRst; + logic [31:0] RvviAxiRdataDelay; + logic [3:0] RvviAxiRstrbDelay; + logic RvviAxiRvalidDelay; + logic Match, Overflow, Mismatch, Threshold; + + assign mem[0] = 32'h0000_1654; // src mac [31:0] + assign mem[1] = 32'h6843_8F54; // dst mac [15:0], src mac [47:32] + assign mem[2] = 32'h4502_1111; // dst mac [47:16] + assign mem[3] = 32'h7274_005c; // "rt", ether type 005c + assign mem[4] = 32'h6e69_6769; // "igin" (trigin) + + flopenr #(32) rvviaxirdatareg(clk, reset, RvviAxiRvalid, RvviAxiRdata, RvviAxiRdataDelay); + flopenr #(4) rvviaxirstrbreg(clk, reset, RvviAxiRvalid, RvviAxiRstrb, RvviAxiRstrbDelay); + flopr #(1) rvviaxirvalidreg(clk, reset, RvviAxiRvalid, RvviAxiRvalidDelay); + + counter #(3) counter(clk, CounterRst, CounterEn, Counter); + + always_ff @(posedge clk) begin + if(reset) CurrState <= STATE_RST; + else CurrState <= NextState; + end + + always_comb begin + case(CurrState) + STATE_RST: if(RvviAxiRvalid) NextState = STATE_COMPARE; + else NextState = STATE_RST; + STATE_COMPARE: if(RvviAxiRlast) NextState = STATE_RST; + else if(Mismatch | Overflow) NextState = STATE_MISMATCH; + else if(Threshold & Match) NextState = STATE_TRIGGER; + else NextState = STATE_COMPARE; + STATE_MISMATCH: if(RvviAxiRlast) NextState = STATE_RST; + else NextState = STATE_MISMATCH; + STATE_TRIGGER: if(RvviAxiRlast) NextState = STATE_RST; + else NextState = STATE_TRIGGER_DONE; + STATE_TRIGGER_DONE: if(RvviAxiRlast) NextState = STATE_RST; + else NextState = STATE_TRIGGER_DONE; + default: NextState = STATE_RST; + endcase + end + + assign Match = (mem[Counter] == RvviAxiRdataDelay) & (CurrState == STATE_COMPARE) & RvviAxiRvalidDelay; + assign Overflow = Counter > 4'd4; + assign Threshold = Counter >= 4'd4; + assign Mismatch = (mem[Counter] != RvviAxiRdataDelay) & (CurrState == STATE_COMPARE) & RvviAxiRvalidDelay; + assign IlaTrigger = CurrState == STATE_TRIGGER; + assign CounterRst = CurrState == STATE_RST; + assign CounterEn = RvviAxiRvalid; + +endmodule From ccf4bb8ddc292fb9bbfe006452b3a3c5a8a38f2a Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 26 Jun 2024 16:15:46 -0700 Subject: [PATCH 053/163] Maybe have the incircuit trigger working. --- fpga/constraints/small-debug.xdc | 31 ++++++++++++++----------------- fpga/src/fpgaTopArtyA7.sv | 8 ++++---- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index c2daf9fe1..b244a1747 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -1,22 +1,20 @@ create_debug_core u_ila_0 ila - - - - set_property C_DATA_DEPTH 8192 [get_debug_cores u_ila_0] set_property C_TRIGIN_EN true [get_debug_cores u_ila_0] set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] -set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0] set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] -set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0] set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0] -set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0] -startgroup set_property C_EN_STRG_QUAL true [get_debug_cores u_ila_0 ] set_property C_ADV_TRIGGER true [get_debug_cores u_ila_0 ] set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0 ] set_property ALL_PROBE_SAME_MU_CNT 4 [get_debug_cores u_ila_0 ] -endgroup +create_debug_port u_ila_0 trig_in +create_debug_port u_ila_0 trig_in_ack +#set_property port_width 1 [get_debug_ports u_ila_0/trig_in] +#set_property port_width 1 [get_debug_ports u_ila_0/trig_in_ack] +#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/trig_in] +connect_debug_port u_ila_0/trig_in [get_nets IlaTrigger] +#connect_debug_port u_ila_0/trig_in_ack [get_nets IlaTriggerAck] connect_debug_port u_ila_0/clk [get_nets CPUCLK] set_property port_width 32 [get_debug_ports u_ila_0/probe0] @@ -53,10 +51,15 @@ set_property port_width 64 [get_debug_ports u_ila_0/probe6] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] +#create_debug_port u_ila_0 probe +#set_property port_width 1 [get_debug_ports u_ila_0/probe7] +#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] +#connect_debug_port u_ila_0/probe7 [get_nets [list {IlaTrigger} ]] + create_debug_port u_ila_0 probe -set_property port_width 32 [get_debug_ports u_ila_0/probe7] +set_property port_width 1 [get_debug_ports u_ila_0/probe7] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] -connect_debug_port u_ila_0/probe7 [get_nets [list {packetizer/FrameCount[0]} {packetizer/FrameCount[1]} {packetizer/FrameCount[2]} {packetizer/FrameCount[3]} {packetizer/FrameCount[4]} {packetizer/FrameCount[5]} {packetizer/FrameCount[6]} {packetizer/FrameCount[7]} {packetizer/FrameCount[8]} {packetizer/FrameCount[9]} {packetizer/FrameCount[10]} {packetizer/FrameCount[11]} {packetizer/FrameCount[12]} {packetizer/FrameCount[13]} {packetizer/FrameCount[14]} {packetizer/FrameCount[15]} {packetizer/FrameCount[16]} {packetizer/FrameCount[17]} {packetizer/FrameCount[18]} {packetizer/FrameCount[19]} {packetizer/FrameCount[20]} {packetizer/FrameCount[21]} {packetizer/FrameCount[22]} {packetizer/FrameCount[23]} {packetizer/FrameCount[24]} {packetizer/FrameCount[25]} {packetizer/FrameCount[26]} {packetizer/FrameCount[27]} {packetizer/FrameCount[28]} {packetizer/FrameCount[29]} {packetizer/FrameCount[30]} {packetizer/FrameCount[31]} ]] +connect_debug_port u_ila_0/probe7 [get_nets [list {RvviAxiWvalid}]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe8] @@ -73,15 +76,9 @@ set_property port_width 1 [get_debug_ports u_ila_0/probe10] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] connect_debug_port u_ila_0/probe10 [get_nets [list {RvviAxiWready}]] -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe11] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] -connect_debug_port u_ila_0/probe11 [get_nets [list {RvviAxiWvalid}]] # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] connect_debug_port dbg_hub/clk [get_nets CPUCLK] -# connect the trig_in in of the ila to the -connect_debug_port u_ila_0/trig_in [get_nets [list {IlaTrigger}]] diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 811d32e4f..8202d735f 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1128,8 +1128,8 @@ module fpgaTop (* mark_debug = "true" *) logic RvviAxiWvalid; (* mark_debug = "true" *) logic RvviAxiWready; - logic RvviAxiRdata [31:0]; - logic RvviAxiRstrb [3:0]; + logic [31:0] RvviAxiRdata; + logic [3:0] RvviAxiRstrb; logic RvviAxiRlast; logic RvviAxiRvalid; (* mark_debug = "true" *) logic IlaTrigger; @@ -1163,8 +1163,8 @@ module fpgaTop ); triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, - .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger) - + .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger); + //assign phy_reset_n = ~bus_struct_reset; assign phy_reset_n = ~1'b0; From dc97ee5f8255740a9aadd206ae64da8e72c0000a Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 2 Jul 2024 09:12:34 -0700 Subject: [PATCH 054/163] Have some sample code which I know works transmisting a packet. --- fpga/rvvidaemon/rvvidaemon.c | 136 +++++++++++++++++++++++++++++------ fpga/rvvidaemon/send-copy.c | 112 +++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 23 deletions(-) create mode 100644 fpga/rvvidaemon/send-copy.c diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index b2ccc2b63..9876ebc20 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -41,9 +41,11 @@ #include <sys/socket.h> #include <net/if.h> #include <netinet/ether.h> +#include <linux/udp.h> #include "rvviApi.h" // *** bug fix me when this file gets included into the correct directory. #include "idv/idv.h" +#include <netinet/in.h> #define DEST_MAC0 0x43 #define DEST_MAC1 0x68 @@ -67,6 +69,8 @@ #define DEFAULT_IF "eno1" FILE *VivadoPipeFP; +int sockfd; +struct ifreq ifopts, if_mac; /* set promiscuous mode */ typedef struct { uint64_t PC; @@ -100,6 +104,7 @@ int ProcessRvviAll(RequiredRVVI_t *InstructionData); void set_gpr(int hart, int reg, uint64_t value); void set_fpr(int hart, int reg, uint64_t value); int state_compare(int hart, uint64_t Minstret); +void SendILATrigger(); int main(int argc, char **argv){ @@ -109,40 +114,57 @@ int main(int argc, char **argv){ return -1; } - // step 1 open a pipe to vivado - if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ - perror("popen"); - exit(1); - } - fputs("open_hw_manager\n", VivadoPipeFP); - fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); - fputs("current_hw_target [get_hw_targets */xilinx_tcf/Digilent/*]\n", VivadoPipeFP); - fputs("open_hw_target\n", VivadoPipeFP); - fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); + /* // step 1 open a pipe to vivado */ + /* if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ */ + /* perror("popen"); */ + /* exit(1); */ + /* } */ + /* fputs("open_hw_manager\n", VivadoPipeFP); */ + /* fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); */ + /* fputs("current_hw_target [get_hw_targets *\/xilinx_tcf/Digilent/\*]\n", VivadoPipeFP); */ + /* fputs("open_hw_target\n", VivadoPipeFP); */ + /* fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); */ - // *** bug these need to made relative paths. - fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); - fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); - fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); - fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); - fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); + /* // *** bug these need to made relative paths. */ + /* fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ + /* fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ + /* fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ + /* fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); */ + /* fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); */ + /* fflush(VivadoPipeFP); */ - int sockfd; uint8_t buf[BUF_SIZ]; int sockopt; - struct ifreq ifopts; /* set promiscuous mode */ struct ether_header *eh = (struct ether_header *) buf; ssize_t headerbytes, numbytes, payloadbytes; + /* Open RAW socket to receive frames */ if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) { + // *** remove. This is not the problem + //if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { perror("socket"); } + printf("sockfd %x\n", sockfd); printf("Here 0\n"); /* Set interface to promiscuous mode - do we need to do this every time? */ + memset(&ifopts, 0, sizeof(struct ifreq)); strncpy(ifopts.ifr_name, argv[1], IFNAMSIZ-1); ioctl(sockfd, SIOCGIFFLAGS, &ifopts); + + /* Get the index of the interface to send on */ + //memset(&if_idx, 0, sizeof(struct ifreq)); + //strncpy(if_idx.ifr_name, argv[1], IFNAMSIZ-1); + if (ioctl(sockfd, SIOCGIFINDEX, &ifopts) < 0) + perror("SIOCGIFINDEX"); + + /* Get the MAC address of the interface to send on */ + memset(&if_mac, 0, sizeof(struct ifreq)); + strncpy(if_mac.ifr_name, argv[1], IFNAMSIZ-1); + if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0) + perror("SIOCGIFHWADDR"); + printf("Here 1\n"); ifopts.ifr_flags |= IFF_PROMISC; ioctl(sockfd, SIOCSIFFLAGS, &ifopts); @@ -163,6 +185,8 @@ int main(int argc, char **argv){ exit(EXIT_FAILURE); } printf("Here 4\n"); + SendILATrigger(); + exit(0); if(!rvviVersionCheck(RVVI_API_VERSION)){ printf("Bad RVVI_API_VERSION\n"); @@ -241,7 +265,8 @@ int main(int argc, char **argv){ printf("Simulation halted due to mismatch\n"); - pclose(VivadoPipeFP); + //pclose(VivadoPipeFP); + printf("closed pipe to vivado\n"); close(sockfd); @@ -291,18 +316,82 @@ int state_compare(int hart, uint64_t Minstret){ } if (result == 0) { + SendILATrigger(); sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); idvMsgError(buf); - fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); - fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); - fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); - fputs("write_hw_ila_data my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); + /* fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); */ + /* fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); */ + /* fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ + /* fputs("write_hw_ila_data -force my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ + /* fflush(VivadoPipeFP); */ return -1; //if (ON_MISMATCH_DUMP_STATE) dump_state(hart); } } +void SendILATrigger(){ + uint8_t buf[BUF_SIZ]; + struct ether_header *eh = (struct ether_header *) buf; + int crc32; + struct sockaddr_ll socket_address; + + eh->ether_dhost[0] = DEST_MAC0; + eh->ether_dhost[1] = DEST_MAC1; + eh->ether_dhost[2] = DEST_MAC2; + eh->ether_dhost[3] = DEST_MAC3; + eh->ether_dhost[4] = DEST_MAC4; + eh->ether_dhost[5] = DEST_MAC5; + //c8:4b:d6:5f:89:25 is the real source mac for this laptop. I don't think it needs to be correct. + /* eh->ether_shost[0] = SRC_MAC0; */ + /* eh->ether_shost[1] = SRC_MAC1; */ + /* eh->ether_shost[2] = SRC_MAC2; */ + /* eh->ether_shost[3] = SRC_MAC3; */ + /* eh->ether_shost[4] = SRC_MAC4; */ + /* eh->ether_shost[5] = SRC_MAC5; */ + eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; + eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; + eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; + eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; + eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; + eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; + eh->ether_type = htons(ETH_P_IP); + //buf[12] = (ETHER_TYPE) >> 8; + //buf[13] = (ETHER_TYPE) && 0xFF; // *** does not work for some reason + buf[13] = 0; + buf[14] = 't'; + buf[15] = 'r'; + buf[16] = 'i'; + buf[17] = 'g'; + buf[18] = 'i'; + buf[19] = 'n'; + memset(&buf[20], 0, 40); // fill 36 bytes of 0 + int i; + printf("buffer: "); + for(i = 0; i < 60; i++){ + printf("%02x ", buf[i]); + } + printf("\n"); + //if (sendto(sockfd, buf, 60, 0, NULL, 0)) { + printf("sockfd %x\n", sockfd); + /* Index of the network device */ + socket_address.sll_ifindex = ifopts.ifr_ifindex; + /* Address length*/ + socket_address.sll_halen = ETH_ALEN; + /* Destination MAC */ + socket_address.sll_addr[0] = DEST_MAC0; + socket_address.sll_addr[1] = DEST_MAC1; + socket_address.sll_addr[2] = DEST_MAC2; + socket_address.sll_addr[3] = DEST_MAC3; + socket_address.sll_addr[4] = DEST_MAC4; + socket_address.sll_addr[5] = DEST_MAC5; + if (sendto(sockfd, buf, 60, MSG_DONTROUTE, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) { + perror("ugh why???????????????????? sendto()"); + exit(3); + } +} + + void set_gpr(int hart, int reg, uint64_t value){ rvviDutGprSet(hart, reg, value); } @@ -465,3 +554,4 @@ void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ byte1 = byte1 >> ShiftAmount; dst[Length-1] = byte1; } + diff --git a/fpga/rvvidaemon/send-copy.c b/fpga/rvvidaemon/send-copy.c new file mode 100644 index 000000000..598e90f45 --- /dev/null +++ b/fpga/rvvidaemon/send-copy.c @@ -0,0 +1,112 @@ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ + +#include <arpa/inet.h> +#include <linux/if_packet.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/ether.h> + +#define DEST_MAC0 0x43 +#define DEST_MAC1 0x68 +#define DEST_MAC2 0x11 +#define DEST_MAC3 0x11 +#define DEST_MAC4 0x02 +#define DEST_MAC5 0x45 + +#define DEFAULT_IF "eth0" +#define BUF_SIZ 1024 + +int main(int argc, char *argv[]) +{ + int sockfd; + struct ifreq if_idx; + struct ifreq if_mac; + int tx_len = 0; + char sendbuf[BUF_SIZ]; + struct ether_header *eh = (struct ether_header *) sendbuf; + struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header)); + struct sockaddr_ll socket_address; + char ifName[IFNAMSIZ]; + + /* Get interface name */ + if (argc > 1) + strcpy(ifName, argv[1]); + else + strcpy(ifName, DEFAULT_IF); + + /* Open RAW socket to send on */ + if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { + perror("socket"); + } + + /* Get the index of the interface to send on */ + memset(&if_idx, 0, sizeof(struct ifreq)); + strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1); + if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) + perror("SIOCGIFINDEX"); + /* Get the MAC address of the interface to send on */ + memset(&if_mac, 0, sizeof(struct ifreq)); + strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1); + if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0) + perror("SIOCGIFHWADDR"); + + /* Construct the Ethernet header */ + memset(sendbuf, 0, BUF_SIZ); + /* Ethernet header */ + eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; + eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; + eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; + eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; + eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; + eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; + eh->ether_dhost[0] = DEST_MAC0; + eh->ether_dhost[1] = DEST_MAC1; + eh->ether_dhost[2] = DEST_MAC2; + eh->ether_dhost[3] = DEST_MAC3; + eh->ether_dhost[4] = DEST_MAC4; + eh->ether_dhost[5] = DEST_MAC5; + /* Ethertype field */ + eh->ether_type = htons(ETH_P_IP); + tx_len += sizeof(struct ether_header); + + /* Packet data */ + sendbuf[tx_len++] = 0xde; + sendbuf[tx_len++] = 0xad; + sendbuf[tx_len++] = 0xbe; + sendbuf[tx_len++] = 0xef; + + /* Index of the network device */ + socket_address.sll_ifindex = if_idx.ifr_ifindex; + /* Address length*/ + socket_address.sll_halen = ETH_ALEN; + /* Destination MAC */ + socket_address.sll_addr[0] = DEST_MAC0; + socket_address.sll_addr[1] = DEST_MAC1; + socket_address.sll_addr[2] = DEST_MAC2; + socket_address.sll_addr[3] = DEST_MAC3; + socket_address.sll_addr[4] = DEST_MAC4; + socket_address.sll_addr[5] = DEST_MAC5; + + int i; + printf("buffer: "); + for(i=0;i<tx_len;i++){ + printf("%02hhx ", sendbuf[i]); + } + printf("\n"); + + /* Send packet */ + if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) + printf("Send failed\n"); + printf("send success!\n"); + return 0; +} From f83e6cf7719e9f073bb75ae08d1289007ec0130e Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 8 Jul 2024 14:48:52 -0500 Subject: [PATCH 055/163] Fixed issue #874. --- testbench/testbench.sv | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/testbench/testbench.sv b/testbench/testbench.sv index e65fed554..5458681f2 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -462,7 +462,7 @@ module testbench; integer StartIndex; integer EndIndex; integer BaseIndex; - integer memFile; + integer memFile, uncoreMemFile; integer readResult; if (P.SDC_SUPPORTED) begin always @(posedge clk) begin @@ -505,8 +505,16 @@ module testbench; end readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile); $fclose(memFile); - end else - $readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.ram.RAM); + end else begin + uncoreMemFile = $fopen(memfilename, "r"); // Is there a better way to test if a file exists? + if (uncoreMemFile == 0) begin + $display("Error: Could not open file %s", memfilename); + $finish; + end else begin + $fclose(uncoreMemFile); + $readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.ram.RAM); + end + end if (TEST == "embench") $display("Read memfile %s", memfilename); end if (CopyRAM) begin From bf69a2e1cd0905d470f9601df7a6143de989acd5 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 9 Jul 2024 12:30:18 -0500 Subject: [PATCH 056/163] Updated to use the newest imperasDV. --- fpga/rvvidaemon/Makefile | 4 +- fpga/rvvidaemon/rvviApi.h | 697 ----------------------------------- fpga/rvvidaemon/rvvidaemon.c | 136 ++----- 3 files changed, 25 insertions(+), 812 deletions(-) delete mode 100644 fpga/rvvidaemon/rvviApi.h diff --git a/fpga/rvvidaemon/Makefile b/fpga/rvvidaemon/Makefile index 4f048302d..26f705a20 100644 --- a/fpga/rvvidaemon/Makefile +++ b/fpga/rvvidaemon/Makefile @@ -1,10 +1,10 @@ all: rvvidaemon rvvidaemon: rvvidaemon.o - gcc $^ /opt/riscv/ImperasDV-OpenHW/Imperas/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model.so -o rvvidaemon + gcc $^ /opt/riscv/ImperasDV-OpenHW/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model.so -o rvvidaemon %.o:%.c - gcc -I/opt/riscv/ImperasDV-OpenHW/Imperas/ImpProprietary/include/host -c $^ -o $@ + gcc -I/opt/riscv/ImperasDV-OpenHW/ImpProprietary/include/host -I/opt/riscv/ImperasDV-OpenHW/ImpPublic/include/host/rvvi/ -c $^ -o $@ clean: rm *.o rvvidaemon diff --git a/fpga/rvvidaemon/rvviApi.h b/fpga/rvvidaemon/rvviApi.h deleted file mode 100644 index d37286781..000000000 --- a/fpga/rvvidaemon/rvviApi.h +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (c) 2005-2023 Imperas Software Ltd., www.imperas.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -/*! \file rvviApi.h - * \brief RVVI interface, C API header. -**/ - -#include <stdint.h> - -typedef uint32_t bool_t; - -#define RVVI_API_VERSION_MAJOR 1 -#define RVVI_API_VERSION_MINOR 34 -#define RVVI_TRUE 1 -#define RVVI_FALSE 0 -#define RVVI_INVALID_INDEX -1 -#define RVVI_MEMORY_PRIVILEGE_READ 1 -#define RVVI_MEMORY_PRIVILEGE_WRITE 2 -#define RVVI_MEMORY_PRIVILEGE_EXEC 4 -#define RVVI_API_VERSION ((RVVI_API_VERSION_MAJOR << 24) | RVVI_API_VERSION_MINOR) - -typedef enum { - RVVI_METRIC_RETIRES = 0, - RVVI_METRIC_TRAPS = 1, - RVVI_METRIC_MISMATCHES = 2, - RVVI_METRIC_COMPARISONS_PC = 3, - RVVI_METRIC_COMPARISONS_GPR = 4, - RVVI_METRIC_COMPARISONS_FPR = 5, - RVVI_METRIC_COMPARISONS_CSR = 6, - RVVI_METRIC_COMPARISONS_VR = 7, - RVVI_METRIC_COMPARISONS_INSBIN = 8, - RVVI_METRIC_CYCLES = 9, - RVVI_METRIC_ERRORS = 10, - RVVI_METRIC_WARNINGS = 11, - RVVI_METRIC_FATALS = 12, -} rvviMetricE; - -#ifdef __cplusplus -extern "C" { -#endif - -/*! \brief Check the compiled RVVI API version. - * - * Makes sure the RVVI implementation linked with matches the versions defined in this header file. This should be called before any other RVVI API function. If this function returns RVVI_FALSE, no other RVVI API function should be called. - * - * \param version Should be set to RVVI_API_VERSION. - * - * \return RVVI_TRUE if versions matches otherwise RVVI_FALSE. -**/ -extern bool_t rvviVersionCheck( - uint32_t version); - -/*! \brief Initialize the DV reference model. - * - * \param programPath File path of the ELF file to be executed. This parameter can be NULL if required. - * - * \return RVVI_TRUE if the reference was initialized successfully else RVVI_FALSE. - * - * \note The reference model will begin execution from the entry point of the provided ELF file but can be overridden by the rvviRefPcSet() function. -**/ -extern bool_t rvviRefInit( - const char *programPath); - -/*! \brief Force the PC of the reference model to be particular value. - * - * \param hartId The hart to change the PC register of. - * \param address The address to change the PC register to. - * - * \return RVVI_TRUE on success else RVVI_FALSE. -**/ -extern bool_t rvviRefPcSet( - uint32_t hartId, - uint64_t address); - -/*! \brief Shutdown the reference module releasing any used resources. - * - * \return Returns RVVI_TRUE if shutdown was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefShutdown(void); - -/*! \brief Notify the reference that a CSR is considered volatile. - * - * \param hartId The hart that will have its CSR made volatile. - * \param csrIndex Index of the CSR register to be considered volatile (0x0 to 0xfff). - * - * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefCsrSetVolatile( - uint32_t hartId, - uint32_t csrIndex); - -/*! \brief Notify the reference that a memory region is volatile. - * - * \param addressLow Lower address of the volatile memory region - * \param addressHigh Upper address of the volatile memory region (inclusive) - * - * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefMemorySetVolatile( - uint64_t addressLow, - uint64_t addressHigh); - -/*! \brief Lookup a net on the reference model and return its index. - * - * \param name The net name to locate. - * - * \return Unique index for this net or RVVI_INVALID_INDEX if it was not found. - * - * \note Please consult the model datasheet for a list of valid net names. - * \note See also, rvviRefNetSet(). -**/ -extern uint64_t rvviRefNetIndexGet( - const char *name); - -/*! \brief Extract a byte from the reference models vector register. - * - * \param hartId The hart to extract the vector register byte from. - * \param vrIndex The vector register index (0 to 31). - * \param byteIndex The byte offset into the vector register (note 0 is LSB). - * - * \return Byte that has been extracted from the vector register. -**/ -extern uint8_t rvviRefVrGet( - uint32_t hartId, - uint32_t vrIndex, - uint32_t byteIndex); - -/*! \brief Notify RVVI that a byte in the DUTs vector register has changed. - * - * \param hartId The hart that has updated its vector register. - * \param vrIndex The vector register index (0 to 31). - * \param byteIndex The byte offset into the vector register (note 0 is LSB). - * \param data New byte value in the DUTs vector register. -**/ -extern void rvviDutVrSet( - uint32_t hartId, - uint32_t vrIndex, - uint32_t byteIndex, - uint8_t data); - -/*! \brief Notify RVVI that a DUT floating point register has been written to. - * - * \param hartId The hart that has updated its FPR. - * \param fprIndex The FPR index within the register file (0 to 31). - * \param value The value that has been written. -**/ -extern void rvviDutFprSet( - uint32_t hartId, - uint32_t fprIndex, - uint64_t value); - -/*! \brief Notify RVVI that a DUT GPR has been written to. - * - * \param hartId The hart that has updated its GPR. - * \param gprIndex The GPR index within the register file. - * \param value The value that has been written. -**/ -extern void rvviDutGprSet( - uint32_t hartId, - uint32_t gprIndex, - uint64_t value); - -/*! \brief Notify RVVI that a DUT CSR has been written to. - * - * \param hartId The hart that has updated its CSR. - * \param csrIndex The CSR index (0x0 to 0xfff). - * \param value The value that has been written. -**/ -extern void rvviDutCsrSet( - uint32_t hartId, - uint32_t csrIndex, - uint64_t value); - -/*! \brief Place a net in a specific net group. - * - * \param netIndex The net index returned prior by rvviRefNetIndexGet(). - * \param group The group index to place this net into. -**/ -extern void rvviRefNetGroupSet( - uint64_t netIndex, - uint32_t group); - -/*! \brief Propagate a net change to the reference model. - * - * \param netIndex The net index returned prior by rvviRefNetIndexGet(). - * \param value The new value to set the net state to. - * \param when Time of arrival of this net, in simulation time. The `when` parameter may be measured in simulation time or cycles. It allows the RVVI-API to know which net changes have arrived at the same time. -**/ -extern void rvviRefNetSet( - uint64_t netIndex, - uint64_t value, - uint64_t when); - -/*! \brief Read the state of a net on the reference model. - * - * \param netIndex The net index returned prior by rvviRefNetIndexGet(). - * - * \return The value present on the specified net. -**/ -extern uint64_t rvviRefNetGet( - uint64_t netIndex); - -/*! \brief Notify the reference that a DUT instruction has retired. - * - * \param hartId The hart that has retired an instruction. - * \param dutPc The address of the instruction that has retired. - * \param dutInsBin The binary instruction representation. - * \param debugMode True if this instruction was executed in debug mode. -**/ -extern void rvviDutRetire( - uint32_t hartId, - uint64_t dutPc, - uint64_t dutInsBin, - bool_t debugMode); - -/*! \brief Notify the reference that the DUT received a trap. - * - * \param hartId The hart that has retired an instruction. - * \param dutPc The address of the instruction that has retired. - * \param dutInsBin The binary instruction representation. -**/ -extern void rvviDutTrap( - uint32_t hartId, - uint64_t dutPc, - uint64_t dutInsBin); - -/*! \brief Invalidate the reference models LR/SC reservation. - * - * \param hartId The hart of which the LR/SC reservation will be made invalid. -**/ -extern void rvviRefReservationInvalidate( - uint32_t hartId); - -/*! \brief Step the reference model until the next event. - * - * \param hartId The ID of the hart that is being stepped. - * - * \return Returns RVVI_TRUE if the step was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefEventStep( - uint32_t hartId); - -/*! \brief Compare all GPR register values between reference and DUT. - * - * \param hartId The ID of the hart that is being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefGprsCompare( - uint32_t hartId); - -/*! \brief Compare GPR registers that have been written to between the reference and DUT. This can be seen as a super set of the rvviRefGprsCompare function. This comparator will also flag differences in the set of registers that have been written to. - * - * \param hartId The ID of the hart that is being compared. - * \param ignoreX0 RVVI_TRUE to not compare writes to the x0 register, which may be treated as a special case, otherwise RVVI_FALSE. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefGprsCompareWritten( - uint32_t hartId, - bool_t ignoreX0); - -/*! \brief Compare retired instruction bytes between reference and DUT. - * - * \param hartId The ID of the hart that is being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefInsBinCompare( - uint32_t hartId); - -/*! \brief Compare program counter for the retired instructions between DUT and the the reference model. - * - * \param hartId The ID of the hart that is being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefPcCompare( - uint32_t hartId); - -/*! \brief Compare a CSR value between DUT and the the reference model. - * - * \param hartId The ID of the hart that is being compared. - * \param csrIndex The index of the CSR register being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefCsrCompare( - uint32_t hartId, - uint32_t csrIndex); - -/*! \brief Enable or disable comparison of a specific CSR during rvviRefCsrsCompare. - * - * \param hartId The ID of the hart that this should apply to. - * \param csrIndex The index of the CSR to enable or disable comparison of. - * \param enableState RVVI_TRUE to enable comparison or RVVI_FALSE to disable. -**/ -extern void rvviRefCsrCompareEnable( - uint32_t hartId, - uint32_t csrIndex, - bool_t enableState); - -/*! \brief Specify a bitmask to direct bit level CSR comparisons. - * - * \param hartId The ID of the hart that this should apply to. - * \param csrIndex The index of the CSR to control the comparison of. - * \param mask Bitmask to enable or disable bits during CSR compare operations. Bits set to 1 will be compared and 0 bits are ignored. -**/ -extern void rvviRefCsrCompareMask( - uint32_t hartId, - uint32_t csrIndex, - uint64_t mask); - -/*! \brief Compare all CSR values between DUT and the the reference model. - * - * This function will compare the value of all CSRs between the reference and the DUT. Note that specific CSRs can be removed from this comparison by using the rvviRefCsrCompareEnable function. - * - * \param hartId The ID of the hart that is being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefCsrsCompare( - uint32_t hartId); - -/*! \brief Compare all RVV vector register values between reference and DUT. - * - * \param hartId The ID of the hart that is being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefVrsCompare( - uint32_t hartId); - -/*! \brief Compare all floating point register values between reference and DUT. - * - * \param hartId The ID of the hart that is being compared. - * - * \return RVVI_FALSE if there are any mismatches, otherwise RVVI_TRUE. -**/ -extern bool_t rvviRefFprsCompare( - uint32_t hartId); - -/*! \brief Write to the GPR of a hart in the reference model. - * - * \param hartId The hart to write the GPR of. - * \param gprIndex Index of the GPR register to write. - * \param gprValue Value to write into the GPR register. -**/ -extern void rvviRefGprSet( - uint32_t hartId, - uint32_t gprIndex, - uint64_t gprValue); - -/*! \brief Read a GPR value from a hart in the reference model. - * - * \param hartId The hart to retrieve the GPR from. - * \param gprIndex Index of the GPR register to read. - * - * \return GPR value read from the reference model. -**/ -extern uint64_t rvviRefGprGet( - uint32_t hartId, - uint32_t gprIndex); - -/*! \brief Read a GPR written mask from the last rvviRefEventStep. - * - * Each bit index in the mask returned indicates if the corresponding GPR has been written to by the reference model. Ie, if bit 3 is set, then X3 was written to. - * - * \param hartId The hart to retrieve the GPR written mask from. - * - * \return The GPR written mask. -**/ -extern uint32_t rvviRefGprsWrittenGet( - uint32_t hartId); - -/*! \brief Return the program counter of a hart in the reference model. - * - * \param hartId The hart to retrieve the PC from. - * - * \return The program counter of the specified hart. -**/ -extern uint64_t rvviRefPcGet( - uint32_t hartId); - -/*! \brief Read a CSR value from a hart in the reference model. - * - * \param hartId The hart to retrieve the CSR from. - * \param csrIndex Index of the CSR register to read (0x0 to 0xfff). - * - * \return The CSR register value read from the specified hart. -**/ -extern uint64_t rvviRefCsrGet( - uint32_t hartId, - uint32_t csrIndex); - -/*! \brief Return the binary representation of the previously retired instruction. - * - * \param hartId The hart to retrieve the instruction from. - * - * \return The instruction bytes. -**/ -extern uint64_t rvviRefInsBinGet( - uint32_t hartId); - -/*! \brief Write the value of a floating point register for a hart in the reference model. - * - * \param hartId The hart to retrieve the FPR register from. - * \param fprIndex Index of the floating point register to read. - * \param fprValue The bit pattern to be written into the floating point register. -**/ -extern void rvviRefFprSet( - uint32_t hartId, - uint32_t fprIndex, - uint64_t fprValue); - -/*! \brief Read a floating point register value from a hart in the reference model. - * - * \param hartId The hart to retrieve the FPR register from. - * \param fprIndex Index of the floating point register to read. - * - * \return The FPR register value read from the specified hart. -**/ -extern uint64_t rvviRefFprGet( - uint32_t hartId, - uint32_t fprIndex); - -/*! \brief Notify RVVI that the DUT has been written to memory. - * - * \param hartId The hart that issued the data bus write. - * \param address The address the hart is writing to. - * \param value The value placed on the data bus. - * \param byteEnableMask The byte enable mask provided for this write. - * - * \note Bus writes larger than 64bits should be reported using multiple calls to this function. - * \note byteEnableMask bit 0 corresponds to address+0, bEnMask bit 1 corresponds to address+1, etc. -**/ -extern void rvviDutBusWrite( - uint32_t hartId, - uint64_t address, - uint64_t value, - uint64_t byteEnableMask); - -/*! \brief Write data to the reference models physical memory space. - * - * \param hartId The hart to write from the perspective of. - * \param address The address being written to. - * \param data The data byte being written into memory. - * \param size Size of the data being written in bytes (1 to 8). -**/ -extern void rvviRefMemoryWrite( - uint32_t hartId, - uint64_t address, - uint64_t data, - uint32_t size); - -/*! \brief Read data from the reference models physical memory space. - * - * \param hartId The hart to read from the perspective of. - * \param address The address being read from. - * \param size Size of the data being read in bytes (1 to 8). - * - * \return The data that has been read from reference memory. -**/ -extern uint64_t rvviRefMemoryRead( - uint32_t hartId, - uint64_t address, - uint32_t size); - -/*! \brief Disassemble an arbitrary instruction encoding. - * - * \param hartId Hart with the ISA we are disassembling for. - * \param address Address of the instruction in memory. - * \param insBin The raw instruction that should be disassembled. - * - * \return Null terminated string containing the disassembly. -**/ -extern const char *rvviDasmInsBin( - uint32_t hartId, - uint64_t address, - uint64_t insBin); - -/*! \brief Return the name of a CSR in the reference model. - * - * \param hartId Hart with the CSR we are looking up the name of. - * \param csrIndex The index of the CSR we are looking up (0x0 to 0xfff inclusive). - * - * \return Null terminated string containing the CSR name. -**/ -extern const char *rvviRefCsrName( - uint32_t hartId, - uint32_t csrIndex); - -/*! \brief Return the ABI name of a GPR in the reference model. - * - * \param hartId Hart with the GPR we are looking up the name of. - * \param gprIndex The index of the GPR we are looking up (0 to 31 inclusive). - * - * \return Null terminated string containing the GPR ABI name. -**/ -extern const char *rvviRefGprName( - uint32_t hartId, - uint32_t gprIndex); - -/*! \brief Check if a CSR is present in the reference model. - * - * \param hartId Hart with the CSR we are checking the presence of. - * \param csrIndex The index of the CSR we are checking for (0x0 to 0xfff inclusive). - * - * \return RVVI_TRUE if the CSR is present in the reference model else RVVI_FALSE. -**/ -extern bool_t rvviRefCsrPresent( - uint32_t hartId, - uint32_t csrIndex); - -/*! \brief Check if floating point registers are present in the reference model. - * - * \param hartId Hart Id we are checking for the presence of floating point registers. - * - * \return RVVI_TRUE if the floating point registers are present in the reference model else RVVI_FALSE. -**/ -extern bool_t rvviRefFprsPresent( - uint32_t hartId); - -/*! \brief Check if vector registers are present in the reference model. - * - * \param hartId Hart Id we are checking for the presence of vector registers. - * - * \return RVVI_TRUE if the vector registers are present in the reference model else RVVI_FALSE. -**/ -extern bool_t rvviRefVrsPresent( - uint32_t hartId); - -/*! \brief Return the name of a FPR in the reference model. - * - * \param hartId Hart with the FPR we are looking up the name of. - * \param fprIndex The index of the FPR we are looking up (0 to 31 inclusive). - * - * \return Null terminated string containing the FPR name. -**/ -extern const char *rvviRefFprName( - uint32_t hartId, - uint32_t fprIndex); - -/*! \brief Return the name of a vector register in the reference model. - * - * \param hartId Hart with the VR we are looking up the name of. - * \param vrIndex The index of the VR we are looking up (0 to 31 inclusive). - * - * \return Null terminated string containing the VR name. -**/ -extern const char *rvviRefVrName( - uint32_t hartId, - uint32_t vrIndex); - -/*! \brief Return a string detailing the last RVVI-API error. - * - * \return The error string or an empty string if no error has occurred. -**/ -extern const char *rvviErrorGet(void); - -/*! \brief Query a verification metric from the reference model. - * - * \param metric An enumeration identifying the metric to query and return. - * - * \return The scalar quantity that has been queried. -**/ -extern uint64_t rvviRefMetricGet( - rvviMetricE metric); - -/*! \brief Set the value of a CSR in the reference model. - * - * \param hartId The hart which we are modifying the CSR of. - * \param csrIndex The index of the CSR we are modifying (0x0 to 0xfff inclusive). - * \param value The value to write into the CSR. -**/ -extern void rvviRefCsrSet( - uint32_t hartId, - uint32_t csrIndex, - uint64_t value); - -/*! \brief Dump the current register state of a hart in the reference model. - * - * \param hartId The hart which we should dump the register state of. -**/ -extern void rvviRefStateDump( - uint32_t hartId); - -/*! \brief Load an additional program into the address space of the processor. - * - * \param programPath File path of the ELF file to be loaded into memory. - * - * \return RVVI_TRUE if the program was loaded successfully otherwise RVVI_FALSE -**/ -extern bool_t rvviRefProgramLoad( - const char *programPath); - -/*! \brief Apply fine grain control over a CSRs volatility in the reference model. - * - * \param hartId The hart that will have its CSR volatility adjusted. - * \param csrIndex Index of the CSR register to have its volatility modified (0x0 to 0xfff). - * \param csrMask Bitmask specifying volatility, set bits will be treated as volatile, clear bits are not - * - * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefCsrSetVolatileMask( - uint32_t hartId, - uint32_t csrIndex, - uint64_t csrMask); - -/*! \brief Pass the current testbench cycle count to the RVVI implementation. - * - * \param cycleCount The current cycle count of the DUT. This value is directly related to, and must be consistent with, the `when` parameter for rvviRefNetSet(). -**/ -extern void rvviDutCycleCountSet( - uint64_t cycleCount); - -/*! \brief Pass a vendor specific integer configuration parameter to the RVVI implementation. - * - * \param configParam The configuration option that is to have its associated value set. This is vendor specific and not defined as part of the RVVI-API. - * \param value An integer containing the data that should be passed to the configuration option. - * - * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefConfigSetInt( - uint64_t configParam, - uint64_t value); - -/*! \brief Pass a vendor specific string configuration parameter to the RVVI implementation. - * - * \param configParam The configuration option that is to have its associated value set. This is vendor specific and not defined as part of the RVVI-API. - * \param value A string containing the data that should be passed to the configuration option. - * - * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefConfigSetString( - uint64_t configParam, - const char *value); - -/*! \brief Given the name of a CSR, its unique index/address will be returned. - * - * \param hartId HartId of the hart containing the CSR we are looking up the index of. - * \param csrName The CSR name for which the CSR index should be retrieved. - * - * \return Returns the CSR index if the operation was successful else RVVI_INVALID_INDEX. -**/ -extern uint32_t rvviRefCsrIndex( - uint32_t hartId, - const char *csrName); - -/*! \brief Set the privilege mode for a region of the address space. - * - * \param addrLo Lower address defining the memory region. - * \param addrHi Upper address defining the memory region (inclusive). - * \param access Access flags for this memory region; a combination of RVVI_PRIV_... flags or 0. - * - * \return Returns RVVI_TRUE if operation was successful else RVVI_FALSE. -**/ -extern bool_t rvviRefMemorySetPrivilege( - uint64_t addrLo, - uint64_t addrHi, - uint32_t access); - -/*! \brief Update a byte in one of the reference models vector registers. - * - * \param hartId The hart that should have its vector register updated. - * \param vrIndex The vector register index (0 to 31). - * \param byteIndex The byte offset into the vector register (note 0 is LSB). - * \param data New byte value to be written into the vector register. -**/ -extern void rvviRefVrSet( - uint32_t hartId, - uint32_t vrIndex, - uint32_t byteIndex, - uint8_t data); - -#ifdef __cplusplus -} // extern "C" -#endif - diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 9876ebc20..b2ccc2b63 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -41,11 +41,9 @@ #include <sys/socket.h> #include <net/if.h> #include <netinet/ether.h> -#include <linux/udp.h> #include "rvviApi.h" // *** bug fix me when this file gets included into the correct directory. #include "idv/idv.h" -#include <netinet/in.h> #define DEST_MAC0 0x43 #define DEST_MAC1 0x68 @@ -69,8 +67,6 @@ #define DEFAULT_IF "eno1" FILE *VivadoPipeFP; -int sockfd; -struct ifreq ifopts, if_mac; /* set promiscuous mode */ typedef struct { uint64_t PC; @@ -104,7 +100,6 @@ int ProcessRvviAll(RequiredRVVI_t *InstructionData); void set_gpr(int hart, int reg, uint64_t value); void set_fpr(int hart, int reg, uint64_t value); int state_compare(int hart, uint64_t Minstret); -void SendILATrigger(); int main(int argc, char **argv){ @@ -114,57 +109,40 @@ int main(int argc, char **argv){ return -1; } - /* // step 1 open a pipe to vivado */ - /* if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ */ - /* perror("popen"); */ - /* exit(1); */ - /* } */ - /* fputs("open_hw_manager\n", VivadoPipeFP); */ - /* fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); */ - /* fputs("current_hw_target [get_hw_targets *\/xilinx_tcf/Digilent/\*]\n", VivadoPipeFP); */ - /* fputs("open_hw_target\n", VivadoPipeFP); */ - /* fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); */ + // step 1 open a pipe to vivado + if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ + perror("popen"); + exit(1); + } + fputs("open_hw_manager\n", VivadoPipeFP); + fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); + fputs("current_hw_target [get_hw_targets */xilinx_tcf/Digilent/*]\n", VivadoPipeFP); + fputs("open_hw_target\n", VivadoPipeFP); + fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); - /* // *** bug these need to made relative paths. */ - /* fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ - /* fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ - /* fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ - /* fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); */ - /* fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); */ - /* fflush(VivadoPipeFP); */ + // *** bug these need to made relative paths. + fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); + fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); + fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); + fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); + fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); + int sockfd; uint8_t buf[BUF_SIZ]; int sockopt; + struct ifreq ifopts; /* set promiscuous mode */ struct ether_header *eh = (struct ether_header *) buf; ssize_t headerbytes, numbytes, payloadbytes; - /* Open RAW socket to receive frames */ if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) { - // *** remove. This is not the problem - //if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { perror("socket"); } - printf("sockfd %x\n", sockfd); printf("Here 0\n"); /* Set interface to promiscuous mode - do we need to do this every time? */ - memset(&ifopts, 0, sizeof(struct ifreq)); strncpy(ifopts.ifr_name, argv[1], IFNAMSIZ-1); ioctl(sockfd, SIOCGIFFLAGS, &ifopts); - - /* Get the index of the interface to send on */ - //memset(&if_idx, 0, sizeof(struct ifreq)); - //strncpy(if_idx.ifr_name, argv[1], IFNAMSIZ-1); - if (ioctl(sockfd, SIOCGIFINDEX, &ifopts) < 0) - perror("SIOCGIFINDEX"); - - /* Get the MAC address of the interface to send on */ - memset(&if_mac, 0, sizeof(struct ifreq)); - strncpy(if_mac.ifr_name, argv[1], IFNAMSIZ-1); - if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0) - perror("SIOCGIFHWADDR"); - printf("Here 1\n"); ifopts.ifr_flags |= IFF_PROMISC; ioctl(sockfd, SIOCSIFFLAGS, &ifopts); @@ -185,8 +163,6 @@ int main(int argc, char **argv){ exit(EXIT_FAILURE); } printf("Here 4\n"); - SendILATrigger(); - exit(0); if(!rvviVersionCheck(RVVI_API_VERSION)){ printf("Bad RVVI_API_VERSION\n"); @@ -265,8 +241,7 @@ int main(int argc, char **argv){ printf("Simulation halted due to mismatch\n"); - //pclose(VivadoPipeFP); - printf("closed pipe to vivado\n"); + pclose(VivadoPipeFP); close(sockfd); @@ -316,82 +291,18 @@ int state_compare(int hart, uint64_t Minstret){ } if (result == 0) { - SendILATrigger(); sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); idvMsgError(buf); - /* fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); */ - /* fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); */ - /* fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ - /* fputs("write_hw_ila_data -force my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ - /* fflush(VivadoPipeFP); */ + fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); + fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); + fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); + fputs("write_hw_ila_data my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); return -1; //if (ON_MISMATCH_DUMP_STATE) dump_state(hart); } } -void SendILATrigger(){ - uint8_t buf[BUF_SIZ]; - struct ether_header *eh = (struct ether_header *) buf; - int crc32; - struct sockaddr_ll socket_address; - - eh->ether_dhost[0] = DEST_MAC0; - eh->ether_dhost[1] = DEST_MAC1; - eh->ether_dhost[2] = DEST_MAC2; - eh->ether_dhost[3] = DEST_MAC3; - eh->ether_dhost[4] = DEST_MAC4; - eh->ether_dhost[5] = DEST_MAC5; - //c8:4b:d6:5f:89:25 is the real source mac for this laptop. I don't think it needs to be correct. - /* eh->ether_shost[0] = SRC_MAC0; */ - /* eh->ether_shost[1] = SRC_MAC1; */ - /* eh->ether_shost[2] = SRC_MAC2; */ - /* eh->ether_shost[3] = SRC_MAC3; */ - /* eh->ether_shost[4] = SRC_MAC4; */ - /* eh->ether_shost[5] = SRC_MAC5; */ - eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; - eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; - eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; - eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; - eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; - eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; - eh->ether_type = htons(ETH_P_IP); - //buf[12] = (ETHER_TYPE) >> 8; - //buf[13] = (ETHER_TYPE) && 0xFF; // *** does not work for some reason - buf[13] = 0; - buf[14] = 't'; - buf[15] = 'r'; - buf[16] = 'i'; - buf[17] = 'g'; - buf[18] = 'i'; - buf[19] = 'n'; - memset(&buf[20], 0, 40); // fill 36 bytes of 0 - int i; - printf("buffer: "); - for(i = 0; i < 60; i++){ - printf("%02x ", buf[i]); - } - printf("\n"); - //if (sendto(sockfd, buf, 60, 0, NULL, 0)) { - printf("sockfd %x\n", sockfd); - /* Index of the network device */ - socket_address.sll_ifindex = ifopts.ifr_ifindex; - /* Address length*/ - socket_address.sll_halen = ETH_ALEN; - /* Destination MAC */ - socket_address.sll_addr[0] = DEST_MAC0; - socket_address.sll_addr[1] = DEST_MAC1; - socket_address.sll_addr[2] = DEST_MAC2; - socket_address.sll_addr[3] = DEST_MAC3; - socket_address.sll_addr[4] = DEST_MAC4; - socket_address.sll_addr[5] = DEST_MAC5; - if (sendto(sockfd, buf, 60, MSG_DONTROUTE, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) { - perror("ugh why???????????????????? sendto()"); - exit(3); - } -} - - void set_gpr(int hart, int reg, uint64_t value){ rvviDutGprSet(hart, reg, value); } @@ -554,4 +465,3 @@ void BitShiftArray(uint8_t *dst, uint8_t *src, uint8_t ShiftAmount, int Length){ byte1 = byte1 >> ShiftAmount; dst[Length-1] = byte1; } - From fd170a6583a22893ec2720ecba3a1f9c6c85c8e4 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 9 Jul 2024 14:09:56 -0500 Subject: [PATCH 057/163] Getting closer. --- fpga/rvvidaemon/rvvidaemon.c | 91 ++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index b2ccc2b63..27e70a1bf 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -67,6 +67,10 @@ #define DEFAULT_IF "eno1" FILE *VivadoPipeFP; +struct sockaddr_ll socket_address; +uint8_t sendbuf[BUF_SIZ]; +struct ether_header *sendeh = (struct ether_header *) sendbuf; +int tx_len = 0; typedef struct { uint64_t PC; @@ -110,22 +114,22 @@ int main(int argc, char **argv){ } // step 1 open a pipe to vivado - if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ - perror("popen"); - exit(1); - } - fputs("open_hw_manager\n", VivadoPipeFP); - fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); - fputs("current_hw_target [get_hw_targets */xilinx_tcf/Digilent/*]\n", VivadoPipeFP); - fputs("open_hw_target\n", VivadoPipeFP); - fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); + /* if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ */ + /* perror("popen"); */ + /* exit(1); */ + /* } */ + /* fputs("open_hw_manager\n", VivadoPipeFP); */ + /* fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); */ + /* fputs("current_hw_target [get_hw_targets *\/xilinx_tcf/Digilent/\*]\n", VivadoPipeFP); */ + /* fputs("open_hw_target\n", VivadoPipeFP); */ + /* fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); */ - // *** bug these need to made relative paths. - fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); - fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); - fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); - fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); - fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); + /* // *** bug these need to made relative paths. */ + /* fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ + /* fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ + /* fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ + /* fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); */ + /* fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); */ int sockfd; uint8_t buf[BUF_SIZ]; @@ -147,6 +151,8 @@ int main(int argc, char **argv){ ifopts.ifr_flags |= IFF_PROMISC; ioctl(sockfd, SIOCSIFFLAGS, &ifopts); printf("Here 2\n"); + if (ioctl(sockfd, SIOCGIFINDEX, &ifopts) < 0) + perror("SIOCGIFINDEX"); /* Allow the socket to be reused - incase connection is closed prematurely */ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) { @@ -168,12 +174,57 @@ int main(int argc, char **argv){ printf("Bad RVVI_API_VERSION\n"); } + /* Construct the Ethernet header */ + memset(sendbuf, 0, BUF_SIZ); + /* Ethernet header */ + sendeh->ether_shost[0] = SRC_MAC0; + sendeh->ether_shost[1] = SRC_MAC1; + sendeh->ether_shost[2] = SRC_MAC2; + sendeh->ether_shost[3] = SRC_MAC3; + sendeh->ether_shost[4] = SRC_MAC4; + sendeh->ether_shost[5] = SRC_MAC5; + sendeh->ether_dhost[0] = DEST_MAC0; + sendeh->ether_dhost[1] = DEST_MAC1; + sendeh->ether_dhost[2] = DEST_MAC2; + sendeh->ether_dhost[3] = DEST_MAC3; + sendeh->ether_dhost[4] = DEST_MAC4; + sendeh->ether_dhost[5] = DEST_MAC5; + /* Ethertype field */ + //eh->ether_type = htons(ETH_P_IP); + sendeh->ether_type = htons(ETHER_TYPE); + tx_len += sizeof(struct ether_header); + /* Packet data */ + sendbuf[tx_len++] = 0xde; + sendbuf[tx_len++] = 0xad; + sendbuf[tx_len++] = 0xbe; + sendbuf[tx_len++] = 0xef; + rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME,"riscv"); rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC"); rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56); rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6); + /* Index of the network device */ + socket_address.sll_ifindex = ifopts.ifr_ifindex; + /* Address length*/ + socket_address.sll_halen = ETH_ALEN; + /* Destination MAC */ + socket_address.sll_addr[0] = DEST_MAC0; + socket_address.sll_addr[1] = DEST_MAC1; + socket_address.sll_addr[2] = DEST_MAC2; + socket_address.sll_addr[3] = DEST_MAC3; + socket_address.sll_addr[4] = DEST_MAC4; + socket_address.sll_addr[5] = DEST_MAC5; + + int i; + printf("buffer: "); + for(i=0;i<tx_len;i++){ + printf("%02hhx ", sendbuf[i]); + } + printf("\n"); + printf("sockfd %x\n", sockfd); + // eventually we want to put the elffiles here rvviRefInit(NULL); rvviRefPcSet(0, 0x1000); @@ -241,7 +292,7 @@ int main(int argc, char **argv){ printf("Simulation halted due to mismatch\n"); - pclose(VivadoPipeFP); + //pclose(VivadoPipeFP); close(sockfd); @@ -293,10 +344,10 @@ int state_compare(int hart, uint64_t Minstret){ if (result == 0) { sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); idvMsgError(buf); - fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); - fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); - fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); - fputs("write_hw_ila_data my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); + /* fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); */ + /* fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); */ + /* fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ + /* fputs("write_hw_ila_data my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ return -1; //if (ON_MISMATCH_DUMP_STATE) dump_state(hart); } From e488ee72250a43738bf5fc100295f0a69df1390c Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 9 Jul 2024 14:16:13 -0500 Subject: [PATCH 058/163] Correctly sending the ethernet frame on a mismatch. Now just need to get vivado to actually trigger. --- fpga/rvvidaemon/rvvidaemon.c | 11 ++++++++-- fpga/rvvidaemon/send-copy.c | 39 +++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 27e70a1bf..f31393e60 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -71,6 +71,7 @@ struct sockaddr_ll socket_address; uint8_t sendbuf[BUF_SIZ]; struct ether_header *sendeh = (struct ether_header *) sendbuf; int tx_len = 0; +int sockfd; typedef struct { uint64_t PC; @@ -131,7 +132,6 @@ int main(int argc, char **argv){ /* fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); */ /* fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); */ - int sockfd; uint8_t buf[BUF_SIZ]; int sockopt; struct ifreq ifopts; /* set promiscuous mode */ @@ -224,7 +224,7 @@ int main(int argc, char **argv){ } printf("\n"); printf("sockfd %x\n", sockfd); - + // eventually we want to put the elffiles here rvviRefInit(NULL); rvviRefPcSet(0, 0x1000); @@ -342,6 +342,13 @@ int state_compare(int hart, uint64_t Minstret){ } if (result == 0) { + /* Send packet */ + if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0){ + printf("Send failed\n"); + }else { + printf("send success!\n"); + } + sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); idvMsgError(buf); /* fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); */ diff --git a/fpga/rvvidaemon/send-copy.c b/fpga/rvvidaemon/send-copy.c index 598e90f45..5d7f85ee8 100644 --- a/fpga/rvvidaemon/send-copy.c +++ b/fpga/rvvidaemon/send-copy.c @@ -15,6 +15,7 @@ #include <sys/socket.h> #include <net/if.h> #include <netinet/ether.h> +#include <unistd.h> #define DEST_MAC0 0x43 #define DEST_MAC1 0x68 @@ -23,8 +24,16 @@ #define DEST_MAC4 0x02 #define DEST_MAC5 0x45 +#define SRC_MAC0 0x54 +#define SRC_MAC1 0x16 +#define SRC_MAC2 0x00 +#define SRC_MAC3 0x00 +#define SRC_MAC4 0x54 +#define SRC_MAC5 0x8F + #define DEFAULT_IF "eth0" #define BUF_SIZ 1024 +#define ETHER_TYPE 0x5c00 // The type defined in packetizer.sv int main(int argc, char *argv[]) { @@ -45,7 +54,8 @@ int main(int argc, char *argv[]) strcpy(ifName, DEFAULT_IF); /* Open RAW socket to send on */ - if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { + //if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { + if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) { perror("socket"); } @@ -63,12 +73,18 @@ int main(int argc, char *argv[]) /* Construct the Ethernet header */ memset(sendbuf, 0, BUF_SIZ); /* Ethernet header */ - eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; - eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; - eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; - eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; - eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; - eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; + /* eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; */ + /* eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; */ + /* eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; */ + /* eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; */ + /* eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; */ + /* eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; */ + eh->ether_shost[0] = SRC_MAC0; + eh->ether_shost[1] = SRC_MAC1; + eh->ether_shost[2] = SRC_MAC2; + eh->ether_shost[3] = SRC_MAC3; + eh->ether_shost[4] = SRC_MAC4; + eh->ether_shost[5] = SRC_MAC5; eh->ether_dhost[0] = DEST_MAC0; eh->ether_dhost[1] = DEST_MAC1; eh->ether_dhost[2] = DEST_MAC2; @@ -76,7 +92,8 @@ int main(int argc, char *argv[]) eh->ether_dhost[4] = DEST_MAC4; eh->ether_dhost[5] = DEST_MAC5; /* Ethertype field */ - eh->ether_type = htons(ETH_P_IP); + //eh->ether_type = htons(ETH_P_IP); + eh->ether_type = htons(ETHER_TYPE); tx_len += sizeof(struct ether_header); /* Packet data */ @@ -103,10 +120,14 @@ int main(int argc, char *argv[]) printf("%02hhx ", sendbuf[i]); } printf("\n"); + printf("sockfd %x\n", sockfd); /* Send packet */ - if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) + if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0){ printf("Send failed\n"); + }else { printf("send success!\n"); + } + close(sockfd); return 0; } From e0a1f0e39f5519e02c3ced8691062f5458aba9b1 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 9 Jul 2024 14:21:43 -0500 Subject: [PATCH 059/163] Really close now. --- fpga/rvvidaemon/rvvidaemon.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index f31393e60..b5438590f 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -194,10 +194,12 @@ int main(int argc, char **argv){ sendeh->ether_type = htons(ETHER_TYPE); tx_len += sizeof(struct ether_header); /* Packet data */ - sendbuf[tx_len++] = 0xde; - sendbuf[tx_len++] = 0xad; - sendbuf[tx_len++] = 0xbe; - sendbuf[tx_len++] = 0xef; + sendbuf[tx_len++] = 't'; + sendbuf[tx_len++] = 'r'; + sendbuf[tx_len++] = 'i'; + sendbuf[tx_len++] = 'g'; + sendbuf[tx_len++] = 'i'; + sendbuf[tx_len++] = 'n'; rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"); rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME,"riscv"); From 67346853330d994552c81b01b942158e8e0f19f2 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 9 Jul 2024 19:04:18 -0500 Subject: [PATCH 060/163] Fixed connection bugs in the top level fpga which preventing sending ethernet frames back to the trigger in unit. --- fpga/src/fpgaTopArtyA7.sv | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 8202d735f..e5a706d0d 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1128,10 +1128,10 @@ module fpgaTop (* mark_debug = "true" *) logic RvviAxiWvalid; (* mark_debug = "true" *) logic RvviAxiWready; - logic [31:0] RvviAxiRdata; +(* mark_debug = "true" *) logic [31:0] RvviAxiRdata; logic [3:0] RvviAxiRstrb; - logic RvviAxiRlast; - logic RvviAxiRvalid; +(* mark_debug = "true" *) logic RvviAxiRlast; +(* mark_debug = "true" *) logic RvviAxiRvalid; (* mark_debug = "true" *) logic IlaTrigger; @@ -1144,8 +1144,9 @@ module fpgaTop eth_mac_mii_fifo #(.TARGET("XILINX"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), - .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), - .rx_axis_tlast(), .rx_axis_tuser(), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(RvviAxiRdata), + .rx_axis_tkeep(RvviAxiRstrb), .rx_axis_tvalid(RvviAxiRvalid), .rx_axis_tready(1'b1), + .rx_axis_tlast(RvviAxiRlast), .rx_axis_tuser(), .mii_rx_clk(phy_rx_clk), .mii_rxd(phy_rxd), From cf986b5fb853d4351ebb232c4867353d01116fde Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Tue, 9 Jul 2024 19:04:51 -0500 Subject: [PATCH 061/163] Really close to having the trigger in module work. Can trigger on the data of the correct frame, but trigger in is still not working. --- fpga/rvvidaemon/rvvidaemon.c | 37 ++++++++++++++++++++++++------------ src/rvvi/triggergen.sv | 6 +++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index b5438590f..6642afe28 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -176,19 +176,32 @@ int main(int argc, char **argv){ /* Construct the Ethernet header */ memset(sendbuf, 0, BUF_SIZ); + sendbuf[0] = DEST_MAC0; + sendbuf[1] = DEST_MAC1; + sendbuf[2] = DEST_MAC2; + sendbuf[3] = DEST_MAC3; + sendbuf[4] = DEST_MAC4; + sendbuf[5] = DEST_MAC5; + sendbuf[6] = SRC_MAC0; + sendbuf[7] = SRC_MAC1; + sendbuf[8] = SRC_MAC2; + sendbuf[9] = SRC_MAC3; + sendbuf[10] = SRC_MAC4; + sendbuf[11] = SRC_MAC5; + /* Ethernet header */ - sendeh->ether_shost[0] = SRC_MAC0; - sendeh->ether_shost[1] = SRC_MAC1; - sendeh->ether_shost[2] = SRC_MAC2; - sendeh->ether_shost[3] = SRC_MAC3; - sendeh->ether_shost[4] = SRC_MAC4; - sendeh->ether_shost[5] = SRC_MAC5; - sendeh->ether_dhost[0] = DEST_MAC0; - sendeh->ether_dhost[1] = DEST_MAC1; - sendeh->ether_dhost[2] = DEST_MAC2; - sendeh->ether_dhost[3] = DEST_MAC3; - sendeh->ether_dhost[4] = DEST_MAC4; - sendeh->ether_dhost[5] = DEST_MAC5; + /* sendeh->ether_shost[0] = SRC_MAC0; */ + /* sendeh->ether_shost[1] = SRC_MAC1; */ + /* sendeh->ether_shost[2] = SRC_MAC2; */ + /* sendeh->ether_shost[3] = SRC_MAC3; */ + /* sendeh->ether_shost[4] = SRC_MAC4; */ + /* sendeh->ether_shost[5] = SRC_MAC5; */ + /* sendeh->ether_dhost[0] = DEST_MAC0; */ + /* sendeh->ether_dhost[1] = DEST_MAC1; */ + /* sendeh->ether_dhost[2] = DEST_MAC2; */ + /* sendeh->ether_dhost[3] = DEST_MAC3; */ + /* sendeh->ether_dhost[4] = DEST_MAC4; */ + /* sendeh->ether_dhost[5] = DEST_MAC5; */ /* Ethertype field */ //eh->ether_type = htons(ETH_P_IP); sendeh->ether_type = htons(ETHER_TYPE); diff --git a/src/rvvi/triggergen.sv b/src/rvvi/triggergen.sv index f8dc4ba8d..76d166380 100644 --- a/src/rvvi/triggergen.sv +++ b/src/rvvi/triggergen.sv @@ -46,9 +46,9 @@ module triggergen import cvw::*; ( logic RvviAxiRvalidDelay; logic Match, Overflow, Mismatch, Threshold; - assign mem[0] = 32'h0000_1654; // src mac [31:0] - assign mem[1] = 32'h6843_8F54; // dst mac [15:0], src mac [47:32] - assign mem[2] = 32'h4502_1111; // dst mac [47:16] + assign mem[0] = 32'h1111_6843; // dst mac [31:0] + assign mem[1] = 32'h1654_4502; // src mac [15:0], dst mac [47:32] + assign mem[2] = 32'h8f54_0000; // src mac [47:16] assign mem[3] = 32'h7274_005c; // "rt", ether type 005c assign mem[4] = 32'h6e69_6769; // "igin" (trigin) From e6dc962d114f1d9c27d6f6859fccfe04ea478f85 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 10 Jul 2024 12:05:10 -0500 Subject: [PATCH 062/163] Yay! the trigger is correctly working now! --- fpga/constraints/small-debug.xdc | 36 +++++++++++++++++++++++++++++++- src/rvvi/triggergen.sv | 19 ++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index b244a1747..44151c6bf 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -19,7 +19,7 @@ connect_debug_port u_ila_0/clk [get_nets CPUCLK] set_property port_width 32 [get_debug_ports u_ila_0/probe0] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] -connect_debug_port u_ila_0/probe0 [get_nets [list {RvviAxiWdata[0]} {RvviAxiWdata[1]} {RvviAxiWdata[2]} {RvviAxiWdata[3]} {RvviAxiWdata[4]} {RvviAxiWdata[5]} {RvviAxiWdata[6]} {RvviAxiWdata[7]} {RvviAxiWdata[8]} {RvviAxiWdata[9]} {RvviAxiWdata[10]} {RvviAxiWdata[11]} {RvviAxiWdata[12]} {RvviAxiWdata[13]} {RvviAxiWdata[14]} {RvviAxiWdata[15]} {RvviAxiWdata[16]} {RvviAxiWdata[17]} {RvviAxiWdata[18]} {RvviAxiWdata[19]} {RvviAxiWdata[20]} {RvviAxiWdata[21]} {RvviAxiWdata[22]} {RvviAxiWdata[23]} {RvviAxiWdata[24]} {RvviAxiWdata[25]} {RvviAxiWdata[26]} {RvviAxiWdata[27]} {RvviAxiWdata[28]} {RvviAxiWdata[29]} {RvviAxiWdata[30]} {RvviAxiWdata[31]} ]] +connect_debug_port u_ila_0/probe0 [get_nets [list {RvviAxiRdata[0]} {RvviAxiRdata[1]} {RvviAxiRdata[2]} {RvviAxiRdata[3]} {RvviAxiRdata[4]} {RvviAxiRdata[5]} {RvviAxiRdata[6]} {RvviAxiRdata[7]} {RvviAxiRdata[8]} {RvviAxiRdata[9]} {RvviAxiRdata[10]} {RvviAxiRdata[11]} {RvviAxiRdata[12]} {RvviAxiRdata[13]} {RvviAxiRdata[14]} {RvviAxiRdata[15]} {RvviAxiRdata[16]} {RvviAxiRdata[17]} {RvviAxiRdata[18]} {RvviAxiRdata[19]} {RvviAxiRdata[20]} {RvviAxiRdata[21]} {RvviAxiRdata[22]} {RvviAxiRdata[23]} {RvviAxiRdata[24]} {RvviAxiRdata[25]} {RvviAxiRdata[26]} {RvviAxiRdata[27]} {RvviAxiRdata[28]} {RvviAxiRdata[29]} {RvviAxiRdata[30]} {RvviAxiRdata[31]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe1] @@ -76,6 +76,40 @@ set_property port_width 1 [get_debug_ports u_ila_0/probe10] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] connect_debug_port u_ila_0/probe10 [get_nets [list {RvviAxiWready}]] +create_debug_port u_ila_0 probe +set_property port_width 3 [get_debug_ports u_ila_0/probe11] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] +connect_debug_port u_ila_0/probe11 [get_nets [list {triggergen/CurrState[0]} {triggergen/CurrState[1]} {triggergen/CurrState[2]}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe12] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe12] +connect_debug_port u_ila_0/probe12 [get_nets [list {RvviAxiRlast}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe13] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe13] +connect_debug_port u_ila_0/probe13 [get_nets [list {RvviAxiRvalid}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe14] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe14] +connect_debug_port u_ila_0/probe14 [get_nets [list {triggergen/IlaTriggerOneCycle}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe15] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe15] +connect_debug_port u_ila_0/probe15 [get_nets [list {triggergen/TriggerReset}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe16] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe16] +connect_debug_port u_ila_0/probe16 [get_nets [list {triggergen/TriggerEn}]] + +create_debug_port u_ila_0 probe +set_property port_width 4 [get_debug_ports u_ila_0/probe17] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe17] +connect_debug_port u_ila_0/probe17 [get_nets [list {triggergen/TriggerCount[0]} {triggergen/TriggerCount[1]} {triggergen/TriggerCount[2]} {triggergen/TriggerCount[3]}]] # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. diff --git a/src/rvvi/triggergen.sv b/src/rvvi/triggergen.sv index 76d166380..1b7e3ef4f 100644 --- a/src/rvvi/triggergen.sv +++ b/src/rvvi/triggergen.sv @@ -45,6 +45,7 @@ module triggergen import cvw::*; ( logic [3:0] RvviAxiRstrbDelay; logic RvviAxiRvalidDelay; logic Match, Overflow, Mismatch, Threshold; +(* mark_debug = "true" *) logic IlaTriggerOneCycle; assign mem[0] = 32'h1111_6843; // dst mac [31:0] assign mem[1] = 32'h1654_4502; // src mac [15:0], dst mac [47:32] @@ -85,8 +86,24 @@ module triggergen import cvw::*; ( assign Overflow = Counter > 4'd4; assign Threshold = Counter >= 4'd4; assign Mismatch = (mem[Counter] != RvviAxiRdataDelay) & (CurrState == STATE_COMPARE) & RvviAxiRvalidDelay; - assign IlaTrigger = CurrState == STATE_TRIGGER; + assign IlaTriggerOneCycle = CurrState == STATE_TRIGGER; assign CounterRst = CurrState == STATE_RST; assign CounterEn = RvviAxiRvalid; +/* -----\/----- EXCLUDED -----\/----- + always_ff @(posedge clk) begin + if(reset) IlaTrigger <= '0; + else if (IlaTriggerOneCycle) IlaTrigger <= '1; + else if (IlaTriggerAck) IlaTrigger <= '0; + else IlaTrigger <= IlaTrigger; + end + -----/\----- EXCLUDED -----/\----- */ + +(* mark_debug = "true" *) logic [3:0] TriggerCount; +(* mark_debug = "true" *) logic TriggerReset, TriggerEn; + counter #(4) triggercounter(clk, reset | TriggerReset, TriggerEn, TriggerCount); + assign TriggerReset = TriggerCount == 4'd10; + assign TriggerEn = IlaTriggerOneCycle | (TriggerCount != 4'd0 & TriggerCount < 4'd10); + assign IlaTrigger = TriggerEn; + endmodule From f0096f5a4329df743cf07f568a59938cc0f25984 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Wed, 10 Jul 2024 15:10:37 -0500 Subject: [PATCH 063/163] Yay. It's actually working! The FPGA/ImperasDV hybrid is working. --- fpga/constraints/marked_debug.txt | 1 + fpga/constraints/small-debug.xdc | 22 +--------------------- src/rvvi/triggergen.sv | 15 ++++++++------- 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/fpga/constraints/marked_debug.txt b/fpga/constraints/marked_debug.txt index 5217067eb..afed3dd23 100644 --- a/fpga/constraints/marked_debug.txt +++ b/fpga/constraints/marked_debug.txt @@ -7,3 +7,4 @@ lsu/lsu.sv: logic PAdrM lsu/lsu.sv: logic ReadDataM lsu/lsu.sv: logic WriteDataM lsu/lsu.sv: logic MemRWM +privileged/csrc.sv: logic HPMCOUNTER_REGW diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index 44151c6bf..10d64c126 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -19,7 +19,7 @@ connect_debug_port u_ila_0/clk [get_nets CPUCLK] set_property port_width 32 [get_debug_ports u_ila_0/probe0] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] -connect_debug_port u_ila_0/probe0 [get_nets [list {RvviAxiRdata[0]} {RvviAxiRdata[1]} {RvviAxiRdata[2]} {RvviAxiRdata[3]} {RvviAxiRdata[4]} {RvviAxiRdata[5]} {RvviAxiRdata[6]} {RvviAxiRdata[7]} {RvviAxiRdata[8]} {RvviAxiRdata[9]} {RvviAxiRdata[10]} {RvviAxiRdata[11]} {RvviAxiRdata[12]} {RvviAxiRdata[13]} {RvviAxiRdata[14]} {RvviAxiRdata[15]} {RvviAxiRdata[16]} {RvviAxiRdata[17]} {RvviAxiRdata[18]} {RvviAxiRdata[19]} {RvviAxiRdata[20]} {RvviAxiRdata[21]} {RvviAxiRdata[22]} {RvviAxiRdata[23]} {RvviAxiRdata[24]} {RvviAxiRdata[25]} {RvviAxiRdata[26]} {RvviAxiRdata[27]} {RvviAxiRdata[28]} {RvviAxiRdata[29]} {RvviAxiRdata[30]} {RvviAxiRdata[31]} ]] +connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe1] @@ -91,26 +91,6 @@ set_property port_width 1 [get_debug_ports u_ila_0/probe13] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe13] connect_debug_port u_ila_0/probe13 [get_nets [list {RvviAxiRvalid}]] -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe14] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe14] -connect_debug_port u_ila_0/probe14 [get_nets [list {triggergen/IlaTriggerOneCycle}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe15] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe15] -connect_debug_port u_ila_0/probe15 [get_nets [list {triggergen/TriggerReset}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe16] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe16] -connect_debug_port u_ila_0/probe16 [get_nets [list {triggergen/TriggerEn}]] - -create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe17] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe17] -connect_debug_port u_ila_0/probe17 [get_nets [list {triggergen/TriggerCount[0]} {triggergen/TriggerCount[1]} {triggergen/TriggerCount[2]} {triggergen/TriggerCount[3]}]] - # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] diff --git a/src/rvvi/triggergen.sv b/src/rvvi/triggergen.sv index 1b7e3ef4f..0a4269024 100644 --- a/src/rvvi/triggergen.sv +++ b/src/rvvi/triggergen.sv @@ -45,7 +45,7 @@ module triggergen import cvw::*; ( logic [3:0] RvviAxiRstrbDelay; logic RvviAxiRvalidDelay; logic Match, Overflow, Mismatch, Threshold; -(* mark_debug = "true" *) logic IlaTriggerOneCycle; + logic IlaTriggerOneCycle; assign mem[0] = 32'h1111_6843; // dst mac [31:0] assign mem[1] = 32'h1654_4502; // src mac [15:0], dst mac [47:32] @@ -99,11 +99,12 @@ module triggergen import cvw::*; ( end -----/\----- EXCLUDED -----/\----- */ -(* mark_debug = "true" *) logic [3:0] TriggerCount; -(* mark_debug = "true" *) logic TriggerReset, TriggerEn; - counter #(4) triggercounter(clk, reset | TriggerReset, TriggerEn, TriggerCount); - assign TriggerReset = TriggerCount == 4'd10; - assign TriggerEn = IlaTriggerOneCycle | (TriggerCount != 4'd0 & TriggerCount < 4'd10); - assign IlaTrigger = TriggerEn; + // this is a bit hacky, but it works! + logic [3:0] TriggerCount; + logic TriggerReset, TriggerEn; + counter #(4) triggercounter(clk, reset | TriggerReset, TriggerEn, TriggerCount); + assign TriggerReset = TriggerCount == 4'd10; + assign TriggerEn = IlaTriggerOneCycle | (TriggerCount != 4'd0 & TriggerCount < 4'd10); + assign IlaTrigger = TriggerEn; endmodule From abf9da01ab9f07815b526f25b3b883fea40b0ef9 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Thu, 11 Jul 2024 10:41:34 -0500 Subject: [PATCH 064/163] code cleanup. --- fpga/rvvidaemon/rvvidaemon.c | 40 ------------------------------------ 1 file changed, 40 deletions(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index 6642afe28..deccb1880 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -66,7 +66,6 @@ //#define ETHER_TYPE 0x0000 // The type defined in packetizer.sv #define DEFAULT_IF "eno1" -FILE *VivadoPipeFP; struct sockaddr_ll socket_address; uint8_t sendbuf[BUF_SIZ]; struct ether_header *sendeh = (struct ether_header *) sendbuf; @@ -114,24 +113,6 @@ int main(int argc, char **argv){ return -1; } - // step 1 open a pipe to vivado - /* if (( VivadoPipeFP = popen("vivado -mode tcl", "w")) == NULL){ */ - /* perror("popen"); */ - /* exit(1); */ - /* } */ - /* fputs("open_hw_manager\n", VivadoPipeFP); */ - /* fputs("connect_hw_server -url localhost:3121\n", VivadoPipeFP); */ - /* fputs("current_hw_target [get_hw_targets *\/xilinx_tcf/Digilent/\*]\n", VivadoPipeFP); */ - /* fputs("open_hw_target\n", VivadoPipeFP); */ - /* fputs("set_property PARAM.FREQUENCY 7500000 [get_hw_targets localhost:3121/xilinx_tcf/Digilent/210319B7CA87A]\n", VivadoPipeFP); */ - - /* // *** bug these need to made relative paths. */ - /* fputs("set_property PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ - /* fputs("set_property FULL_PROBES.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.ltx} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ - /* fputs("set_property PROGRAM.FILE {/home/ross/repos/cvw/fpga/generator/WallyFPGA.runs/impl_1/fpgaTop.bit} [get_hw_devices xc7a100t_0]\n", VivadoPipeFP); */ - /* fputs("refresh_hw_device [lindex [get_hw_devices xc7a100t_0] 0]\n", VivadoPipeFP); */ - /* fputs("[get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}]]\n", VivadoPipeFP); */ - uint8_t buf[BUF_SIZ]; int sockopt; struct ifreq ifopts; /* set promiscuous mode */ @@ -189,21 +170,6 @@ int main(int argc, char **argv){ sendbuf[10] = SRC_MAC4; sendbuf[11] = SRC_MAC5; - /* Ethernet header */ - /* sendeh->ether_shost[0] = SRC_MAC0; */ - /* sendeh->ether_shost[1] = SRC_MAC1; */ - /* sendeh->ether_shost[2] = SRC_MAC2; */ - /* sendeh->ether_shost[3] = SRC_MAC3; */ - /* sendeh->ether_shost[4] = SRC_MAC4; */ - /* sendeh->ether_shost[5] = SRC_MAC5; */ - /* sendeh->ether_dhost[0] = DEST_MAC0; */ - /* sendeh->ether_dhost[1] = DEST_MAC1; */ - /* sendeh->ether_dhost[2] = DEST_MAC2; */ - /* sendeh->ether_dhost[3] = DEST_MAC3; */ - /* sendeh->ether_dhost[4] = DEST_MAC4; */ - /* sendeh->ether_dhost[5] = DEST_MAC5; */ - /* Ethertype field */ - //eh->ether_type = htons(ETH_P_IP); sendeh->ether_type = htons(ETHER_TYPE); tx_len += sizeof(struct ether_header); /* Packet data */ @@ -307,7 +273,6 @@ int main(int argc, char **argv){ printf("Simulation halted due to mismatch\n"); - //pclose(VivadoPipeFP); close(sockfd); @@ -366,12 +331,7 @@ int state_compare(int hart, uint64_t Minstret){ sprintf(buf, "MISMATCH @ instruction # %ld\n", Minstret); idvMsgError(buf); - /* fputs("run_hw_ila [get_hw_ilas -of_objects [get_hw_devices xc7a100t_0] -filter {CELL_NAME=~\"u_ila_0\"}] -trigger_now\n", VivadoPipeFP); */ - /* fputs("current_hw_ila_data [upload_hw_ila_data hw_ila_1]\n", VivadoPipeFP); */ - /* fputs("display_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ - /* fputs("write_hw_ila_data my_hw_ila_data [current_hw_ila_data]\n", VivadoPipeFP); */ return -1; - //if (ON_MISMATCH_DUMP_STATE) dump_state(hart); } } From c72f0fd504590abd29c40954754b65bbc1ebac12 Mon Sep 17 00:00:00 2001 From: Ross Thompson <ross1728@gmail.com> Date: Thu, 11 Jul 2024 10:49:06 -0500 Subject: [PATCH 065/163] Added csr comparison. --- fpga/rvvidaemon/rvvidaemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/rvvidaemon/rvvidaemon.c b/fpga/rvvidaemon/rvvidaemon.c index deccb1880..1e9d17f66 100644 --- a/fpga/rvvidaemon/rvvidaemon.c +++ b/fpga/rvvidaemon/rvvidaemon.c @@ -316,7 +316,7 @@ int state_compare(int hart, uint64_t Minstret){ result &= rvviRefInsBinCompare(hart); result &= rvviRefGprsCompare(hart); result &= rvviRefFprsCompare(hart); - //result &= rvviRefCsrCompare(hart); + result &= rvviRefCsrsCompare(hart); } else { result = 0; } From 1a2607c3d93539b12884d07d53617ba808ed06cd Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Thu, 11 Jul 2024 10:53:18 -0500 Subject: [PATCH 066/163] Commented out riscv,isa-extensions from Arty device tree until Linux kernel is updated. --- linux/devicetree/wally-artya7.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/devicetree/wally-artya7.dts b/linux/devicetree/wally-artya7.dts index 1ad559bbc..490858d96 100644 --- a/linux/devicetree/wally-artya7.dts +++ b/linux/devicetree/wally-artya7.dts @@ -31,7 +31,7 @@ status = "okay"; compatible = "riscv"; riscv,isa = "rv64imafdcsu"; - riscv,isa-extensions = "imafdc", "sstc", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zicbom", "zicbop", "zicbopz", "zicntr", "zicsr", "zifencei", "zihpm"; + // riscv,isa-extensions = "imafdc", "sstc", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zicbom", "zicbop", "zicbopz", "zicntr", "zicsr", "zifencei", "zihpm"; mmu-type = "riscv,sv48"; interrupt-controller { From 7f72fb8583627fee4d7b9d120a086adbc10c91c4 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 12 Jul 2024 09:28:54 -0500 Subject: [PATCH 067/163] Updated riscv,isa-extensions property with the correct syntax. Added riscv,cbom-block-size. --- linux/devicetree/wally-artya7.dts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/devicetree/wally-artya7.dts b/linux/devicetree/wally-artya7.dts index 490858d96..87933bcc0 100644 --- a/linux/devicetree/wally-artya7.dts +++ b/linux/devicetree/wally-artya7.dts @@ -31,7 +31,9 @@ status = "okay"; compatible = "riscv"; riscv,isa = "rv64imafdcsu"; - // riscv,isa-extensions = "imafdc", "sstc", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zicbom", "zicbop", "zicbopz", "zicntr", "zicsr", "zifencei", "zihpm"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "sstc", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zicbom", "zicbop", "zicbopz", "zicntr", "zicsr", "zifencei", "zihpm"; + riscv,cbom-block-size = <64>; mmu-type = "riscv,sv48"; interrupt-controller { From 459eaaef6a5819b8a98063117582701684b43ca9 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Sun, 14 Jul 2024 20:08:33 -0700 Subject: [PATCH 068/163] Initial effort to make testbench_fp compatible with Verilator without breaking Questa --- testbench/testbench_fp.sv | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/testbench/testbench_fp.sv b/testbench/testbench_fp.sv index 5479e0deb..61fa12fcc 100644 --- a/testbench/testbench_fp.sv +++ b/testbench/testbench_fp.sv @@ -660,7 +660,9 @@ module testbench_fp; tt0 = $sformatf("%s", Tests[TestNum]); testname = {pp, tt0}; //$display("Here you are %s", testname); - $display("\n\nRunning %s vectors ", Tests[TestNum]); + // clear the vectors + for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = '1; + $display("\n\nRunning %s vectors ", Tests[TestNum]); $readmemh(testname, TestVectors); // set the test index to 0 TestNum = 0; @@ -774,9 +776,9 @@ module testbench_fp; // Check if the correct answer and result is a NaN always_comb begin if (UnitVal === `CVTINTUNIT | UnitVal === `CMPUNIT) begin - // an integer output can't be a NaN - AnsNaN = 1'b0; - ResNaN = 1'b0; + // an integer output can't be a NaN + AnsNaN = 1'b0; + ResNaN = 1'b0; end else if (UnitVal === `CVTFPUNIT) begin case (OpCtrlVal[1:0]) @@ -894,11 +896,12 @@ module testbench_fp; if (reset) state <= S0; else - state <= nextstate; + state <= nextstate; // Increment the vector when Done with each test - if (state == Done) - VectorNum += 1; // increment the vector + if (state == Done) begin + VectorNum += 1; // increment the vector + end end @@ -982,14 +985,16 @@ module testbench_fp; $display("TestNum %d VectorNum %d OpCtrl %d", TestNum, VectorNum, OpCtrl[TestNum]); $display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Expected: %h %h", X[P.FLEN-1:0], Y[P.FLEN-1:0], Z[P.FLEN-1:0], SrcA, Res[P.FLEN-1:0], ResFlg, Ans[P.FLEN-1:0], AnsFlg); + //$display(" fma.Xs %h Xe %h Xm %h Ys %h Ye %h Ym %h Ss %h Se %h Sm %h", fma.Xs, fma.Xe, fma.Xm, fma.Ys, fma.Ye, fma.Ym, fma.Ss, fma.Se, fma.Sm); + //$display(" readvectors.unpack.X %h Xs %h Xe %h Xm %h", readvectors.unpack.X, readvectors.unpack.Xs, readvectors.unpack.Xe, readvectors.unpack.Xm); $stop; end - if (TestVectors[VectorNum][0] === 1'bx & Tests[TestNum] !== "") begin // if reached the eof + if (TestVectors[VectorNum] == '1 & Tests[TestNum] !== "") begin // if reached the eof // increment the test TestNum += 1; // clear the vectors - for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = {P.Q_LEN*4+8{1'bx}}; + for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = '1; // read next files $readmemh({`PATH, Tests[TestNum]}, TestVectors); // set the vector index back to 0 @@ -999,12 +1004,12 @@ module testbench_fp; // increment the rounding mode or loop back to rne if (FrmNum < 4) FrmNum += 1; else begin - FrmNum = 0; + FrmNum = 0; // Add some time as a buffer between tests at the end of each test - // (to be removed) - repeat (10) - @(posedge clk); - end + // (to be removed, but as of 7/14/24 breaks Verilator sqrt sim to remove dh) + repeat (10) + @(posedge clk); + end // if no more Tests - finish if (Tests[TestNum] === "") begin $display("\nAll Tests completed with %d errors\n", errors); @@ -1052,9 +1057,9 @@ module readvectors import cvw::*; #(parameter cvw_t P) ( // apply test vectors on rising edge of clk // Format of vectors Inputs(1/2/3)_AnsFlg - always @(VectorNum) begin + always @(posedge clk) begin AnsFlg = TestVector[4:0]; - //$display("Entering readvectors with VectorNum=%d, TestVector=%x, Unit=%d, Fmt=%d, OpCtrl=%d", VectorNum, TestVector, Unit, Fmt, OpCtrl); + //$display(" Entering readvectors with VectorNum=%d, TestVector=%x, Unit=%d, Fmt=%d, OpCtrl=%d", VectorNum, TestVector, Unit, Fmt, OpCtrl); */ case (Unit) `FMAUNIT: case (Fmt) @@ -1076,7 +1081,6 @@ module readvectors import cvw::*; #(parameter cvw_t P) ( X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+4*(P.D_LEN)-1:8+3*(P.D_LEN)]}; Y = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; Z = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+P.D_LEN]}; - $display("Read %x %x %x", X, Y, Z); end else begin X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; From affe15191e51a9a433e238907ca1bb2bc2c63826 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 03:44:14 -0700 Subject: [PATCH 069/163] Fixed wsim running iterelf tests/coverage --- bin/wsim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/wsim b/bin/wsim index 85afb7780..68c6ce019 100755 --- a/bin/wsim +++ b/bin/wsim @@ -44,7 +44,7 @@ elif (args.elf != ""): print("ELF file not found: " + args.elf) exit(1) -if(args.testsuite.endswith('.elf')): +if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; check if testsuite has a .elf extension and use that instead if (os.path.isfile(args.testsuite)): ElfFile = "+ElfFile=" + os.path.abspath(args.testsuite) args.testsuite=args.testsuite.rsplit('/', 1)[1] From 467436e30cca33ca044919d70faac3078f10bc6a Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 05:32:16 -0700 Subject: [PATCH 070/163] Renamed --coverage to --ccov and moved UCDB files to questa/ucdb --- Makefile | 8 +++++--- bin/regression-wally | 20 ++++++++++---------- bin/wsim | 12 ++++++------ sim/Makefile | 43 +++++++++++++++++++++---------------------- sim/questa/wally.do | 22 +++++++++++++--------- 5 files changed, 55 insertions(+), 50 deletions(-) diff --git a/Makefile b/Makefile index 740287dcc..050f066fa 100644 --- a/Makefile +++ b/Makefile @@ -91,9 +91,11 @@ combine_functcov: mkdir -p ${SIM}/questa/functcov mkdir -p ${SIM}/questa/functcov_logs cd ${SIM}/questa/functcov && rm -rf * - run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 - run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 - run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 + wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf > ${SIM}/questa/functcov_logs/add.log 2>&1 + + #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 + #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 + #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 vcover merge ${SIM}/questa/functcov/functcov.ucdb ${SIM}/questa/functcov/*.ucdb ${SIM}/questa/functcov_ucdbs/* -suppress 6854 -64 # vcover merge ${SIM}/questa/functcov/functcov.ucdb ${SIM}/questa/functcov_ucdbs/* -suppress 6854 -64 diff --git a/bin/regression-wally b/bin/regression-wally index 8225968aa..a059bf648 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -320,7 +320,7 @@ coveragesim = "questa" # Questa is required for code/functional coverage #defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready defaultsim = "verilator" # Default simulator for all other tests -coverage = '--coverage' in sys.argv +ccov = '--ccov' in sys.argv fp = '--fp' in sys.argv nightly = '--nightly' in sys.argv testfloat = '--testfloat' in sys.argv @@ -334,8 +334,8 @@ else: nightMode = "" sims = [defaultsim] -if (coverage): # only run RV64GC tests in coverage mode - coverStr = '--coverage' +if (ccov): # only run RV64GC tests in coverage mode + coverStr = '--ccov' else: coverStr = '' @@ -357,7 +357,7 @@ if (buildroot): # addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight -if (coverage): # only run RV64GC tests on Questa in coverage mode +if (ccov): # only run RV64GC tests on Questa in code coverage mode addTests(tests64gc_nofp, "questa") if (fp): addTests(tests64gc_fp, "questa") @@ -385,7 +385,7 @@ if (nightly): tc = TestCase( name="lockstep_wally-riscv-arch-test", variant="rv64gc", - cmd="iterelf " + WALLY + "/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege > " + sim_log, + cmd="iterelf " + WALLY + "/tests/riscof/work/wally-riscv-arch-test/rv64i_m > " + sim_log, grepstr="SUCCESS! All tests ran without failures", grepfile = sim_log) configs.append(tc) @@ -393,7 +393,7 @@ if (nightly): # testfloat tests if (testfloat): # for testfloat alone, just run testfloat tests configs = [] -if (testfloat or nightly): # for nightly, run testfloat along with othres +if (testfloat or nightly): # for nightly, run testfloat along with others testfloatsim = "questa" # change to Verilator when Issue #707 about testfloat not running Verilator is resolved testfloatconfigs = ["fdqh_ieee_rv64gc", "fdq_ieee_rv64gc", "fdh_ieee_rv64gc", "fd_ieee_rv64gc", "fh_ieee_rv64gc", "f_ieee_rv64gc", "fdqh_ieee_rv32gc", "f_ieee_rv32gc"] for config in testfloatconfigs: @@ -458,7 +458,7 @@ if (testfloat or nightly): # for nightly, run testfloat along with othres def main(): """Run the tests and count the failures""" - global configs, coverage + global configs, ccov os.chdir(regressionDir) dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"] for d in dirs: @@ -472,7 +472,7 @@ def main(): os.chdir(regressionDir) os.system('./make-tests.sh | tee ./logs/make-tests.log') - elif '--coverage' in sys.argv: + elif '--ccov' in sys.argv: TIMEOUT_DUR = 20*60 # seconds os.system('rm -f questa/cov/*.ucdb') elif '--nightly' in sys.argv: @@ -497,8 +497,8 @@ def main(): print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR)) # Coverage report - if coverage: - os.system('make QuestaCoverage') + if ccov: + os.system('make QuestaCodeCoverage') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/bin/wsim b/bin/wsim index 68c6ce019..f5c297067 100755 --- a/bin/wsim +++ b/bin/wsim @@ -26,8 +26,8 @@ parser.add_argument("--elf", "-e", help="ELF File name; use if name does not end parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilator", "vcs"], default="questa") parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") -parser.add_argument("--coverage", "-c", help="Code & Functional Coverage", action="store_true") -parser.add_argument("--fcov", "-f", help="Code & Functional Coverage", action="store_true") +parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") +parser.add_argument("--fcov", "-f", help="Functional Coverage", action="store_true") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true") parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") @@ -55,7 +55,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che # Validate arguments -if (args.gui or args.coverage or args.fcov or args.lockstep): +if (args.gui or args.ccov or args.fcov or args.lockstep): if args.sim not in ["questa", "vcs"]: print("Option only supported for Questa and VCS") exit(1) @@ -86,14 +86,14 @@ else: flags = suffix + " " + ImperasPlusArgs # other flags -if (args.coverage): - flags += " --coverage" +if (args.ccov): + flags += " --ccov" if (args.fcov): flags += " --fcov" # create the output sub-directories. regressionDir = WALLY + '/sim/' -for d in ["logs", "wkdir", "cov"]: +for d in ["logs", "wkdir", "cov", "ucdb"]: try: os.mkdir(regressionDir+args.sim+"/"+d) except: diff --git a/sim/Makefile b/sim/Makefile index 09d417124..e8fe3c860 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -17,28 +17,27 @@ all: riscoftests memfiles coveragetests deriv wally-riscv-arch-test: wallyriscoftests memfiles -QuestaCoverage: questa/cov/rv64gc_arch64i.ucdb - #iter-elf.bash --cover --search ../tests/coverage - vcover merge -out questa/cov/cov.ucdb questa/cov/rv64gc_arch64i.ucdb questa/cov/rv64gc*.ucdb -logfile questa/cov/log -# vcover merge -out questa/cov/cov.ucdb questa/cov/rv64gc_arch64i.ucdb questa/cov/rv64gc*.ucdb questa/cov/buildroot_buildroot.ucdb riscv.ucdb -logfile questa/cov/log - vcover report -details questa/cov/cov.ucdb > questa/cov/rv64gc_coverage_details.rpt - vcover report questa/cov/cov.ucdb -details -instance=/core/ebu. > questa/cov/rv64gc_coverage_ebu.rpt - vcover report questa/cov/cov.ucdb -details -instance=/core/priv. > questa/cov/rv64gc_coverage_priv.rpt - vcover report questa/cov/cov.ucdb -details -instance=/core/ifu. > questa/cov/rv64gc_coverage_ifu.rpt - vcover report questa/cov/cov.ucdb -details -instance=/core/lsu. > questa/cov/rv64gc_coverage_lsu.rpt - vcover report questa/cov/cov.ucdb -details -instance=/core/fpu. > questa/cov/rv64gc_coverage_fpu.rpt - vcover report questa/cov/cov.ucdb -details -instance=/core/ieu. > questa/cov/rv64gc_coverage_ieu.rpt - vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/ebu. > questa/cov/rv64gc_uncovered_ebu.rpt - vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/priv. > questa/cov/rv64gc_uncovered_priv.rpt - vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/ifu. > questa/cov/rv64gc_uncovered_ifu.rpt - vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/lsu. > questa/cov/rv64gc_uncovered_lsu.rpt - vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/fpu. > questa/cov/rv64gc_uncovered_fpu.rpt - vcover report questa/cov/cov.ucdb -below 100 -details -instance=/core/ieu. > questa/cov/rv64gc_uncovered_ieu.rpt - vcover report -hierarchical questa/cov/cov.ucdb > questa/cov/rv64gc_coverage_hierarchical.rpt - vcover report -below 100 -hierarchical questa/cov/cov.ucdb > questa/cov/rv64gc_uncovered_hierarchical.rpt -# vcover report -below 100 questa/cov/cov.ucdb > questa/cov/rv64gc_coverage.rpt -# vcover report -recursive questa/cov/cov.ucdb > questa/cov/rv64gc_recursive.rpt - vcover report -details -threshH 100 -html questa/cov/cov.ucdb +QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb + vcover merge -out questa/ucdb/cov.ucdb questa/ucdb/rv64gc_arch64i.ucdb questa/ucdb/rv64gc*.ucdb -logfile questa/cov/log +# vcover merge -out questa/ucdb/cov.ucdb questa/ucdb/rv64gc_arch64i.ucdb questa/ucdb/rv64gc*.ucdb questa/ucdb/buildroot_buildroot.ucdb riscv.ucdb -logfile questa/cov/log + vcover report -details questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage_details.rpt + vcover report questa/ucdb/cov.ucdb -details -instance=/core/ebu. > questa/cov/rv64gc_coverage_ebu.rpt + vcover report questa/ucdb/cov.ucdb -details -instance=/core/priv. > questa/cov/rv64gc_coverage_priv.rpt + vcover report questa/ucdb/cov.ucdb -details -instance=/core/ifu. > questa/cov/rv64gc_coverage_ifu.rpt + vcover report questa/ucdb/cov.ucdb -details -instance=/core/lsu. > questa/cov/rv64gc_coverage_lsu.rpt + vcover report questa/ucdb/cov.ucdb -details -instance=/core/fpu. > questa/cov/rv64gc_coverage_fpu.rpt + vcover report questa/ucdb/cov.ucdb -details -instance=/core/ieu. > questa/cov/rv64gc_coverage_ieu.rpt + vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/ebu. > questa/cov/rv64gc_uncovered_ebu.rpt + vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/priv. > questa/cov/rv64gc_uncovered_priv.rpt + vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/ifu. > questa/cov/rv64gc_uncovered_ifu.rpt + vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/lsu. > questa/cov/rv64gc_uncovered_lsu.rpt + vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/fpu. > questa/cov/rv64gc_uncovered_fpu.rpt + vcover report questa/ucdb/cov.ucdb -below 100 -details -instance=/core/ieu. > questa/cov/rv64gc_uncovered_ieu.rpt + vcover report -hierarchical questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage_hierarchical.rpt + vcover report -below 100 -hierarchical questa/ucdb/cov.ucdb > questa/cov/rv64gc_uncovered_hierarchical.rpt +# vcover report -below 100 questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage.rpt +# vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt + vcover report -details -threshH 100 -html questa/ucdb/cov.ucdb allclean: clean all diff --git a/sim/questa/wally.do b/sim/questa/wally.do index a0e6fdbb6..c3dbc3b0f 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -8,7 +8,7 @@ # # Takes 1:10 to run RV64IC tests using gui -# Usage: do wally-batch.do <config> <testcases> <testbench> [-coverage] [+acc] [any number of +value] [any number of -G VAR=VAL] +# Usage: do wally-batch.do <config> <testcases> <testbench> [--ccov] [--fcov] [+acc] [any number of +value] [any number of -G VAR=VAL] # Example: do wally-batch.do rv64gc arch64i testbench # Use this wally-batch.do file to run this example. @@ -40,7 +40,7 @@ vlib ${WKDIR} # Create directory for coverage data mkdir -p cov -set coverage 0 +set ccov 0 set CoverageVoptArg "" set CoverageVsimArg "" @@ -104,9 +104,9 @@ if {$AccIndex >= 0} { } # if +coverage found set flag and remove from list -set CoverageIndex [lsearch -exact $lst "--coverage"] +set CoverageIndex [lsearch -exact $lst "--ccov"] if {$CoverageIndex >= 0} { - set coverage 1 + set ccov 1 set CoverageVoptArg "+cover=sbecf" set CoverageVsimArg "-coverage" set lst [lreplace $lst $CoverageIndex $CoverageIndex] @@ -166,7 +166,7 @@ foreach otherArg $lst { if {$DEBUG > 0} { echo "GUI = $GUI" - echo "coverage = $coverage" + echo "ccov = $ccov" echo "lockstep = $lockstep" echo "FunctCoverage = $FunctCoverage" echo "remaining list = $lst" @@ -215,14 +215,18 @@ if { ${GUI} } { } } +if {$ccov || $FunctCoverage} { + set UCDB ${WALLY}/sim/questa/ucdb/${CFG}_${TESTSUITE}.ucdb + echo "Saving coverage to ${UCDB}" + coverage save -instance /testbench/dut/core ${UCDB} +} + run -all # power off -r /dut/core/* -if {$coverage || $FunctCoverage} { - set UCDB ${WALLY}/sim/questa/cov/${CFG}_${TESTSUITE}.ucdb - echo "Saving coverage to ${UCDB}" +# Code coverage exclusions +if {$ccov} { do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration - coverage save -instance /testbench/dut/core ${UCDB} } # These aren't doing anything helpful From 3ce92ab0a59210092109d4fed1c024ccaabb0069 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 05:34:50 -0700 Subject: [PATCH 071/163] Ignoring more sim files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3eba7966b..74bfca985 100644 --- a/.gitignore +++ b/.gitignore @@ -196,10 +196,12 @@ sim/questa/cov sim/questa/covhtmlreport/ sim/questa/logs sim/questa/wkdir +sim/questa/ucdb sim/verilator/logs sim/verilator/wkdir sim/vcs/logs sim/vcs/wkdir +sim/vcs/ucdb benchmarks/coremark/coremark_results.csv fpga/zsbl/OBJ/* fpga/zsbl/bin/* From c3267e8fa4f9eea9677022c453b34cef811e3123 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 05:46:35 -0700 Subject: [PATCH 072/163] Fixed .gitignore --- .gitignore | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 74bfca985..90864dc0f 100644 --- a/.gitignore +++ b/.gitignore @@ -193,7 +193,7 @@ config/deriv docs/docker/buildroot-config-src docs/docker/testvector-generation sim/questa/cov -sim/questa/covhtmlreport/ +sim/covhtmlreport/ sim/questa/logs sim/questa/wkdir sim/questa/ucdb diff --git a/Makefile b/Makefile index 050f066fa..2431614d1 100644 --- a/Makefile +++ b/Makefile @@ -107,7 +107,7 @@ combine_functcov: grep "Total Coverage By Instance" ${SIM}/questa/functcov/functcov.ucdb.log remove_functcov_artifacts: - rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/functcov.log covhtmlreport/ ${SIM}/questa/functcov_logs/ ${SIM}/questa/functcov_ucdbs/ ${SIM}/questa/functcov/ -rf + rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/functcov.log ${SIM}/questa/covhtmlreport/ ${SIM}/questa/functcov_logs/ ${SIM}/questa/functcov_ucdbs/ ${SIM}/questa/functcov/ -rf collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov From ff15671878735ca32333da3023d7650e48e3ddfe Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 14:19:37 -0700 Subject: [PATCH 073/163] Ignore functional coverage outputs --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 90864dc0f..0d8423d82 100644 --- a/.gitignore +++ b/.gitignore @@ -197,6 +197,9 @@ sim/covhtmlreport/ sim/questa/logs sim/questa/wkdir sim/questa/ucdb +sim/questa/fcov +sim/questa/fcov_logs +sim/questa/fcov_ucdb sim/verilator/logs sim/verilator/wkdir sim/vcs/logs From ac05fa55537232d509cdc07f49f7e0c35b56d217 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 14:20:48 -0700 Subject: [PATCH 074/163] Attempt at functional coverage; breaks code and functional coverage --- Makefile | 86 --------------------------------------- bin/wsim | 2 +- sim/Makefile | 98 ++++++++++++++++++++++++++++++++++++++------- sim/questa/wally.do | 20 ++++++--- 4 files changed, 99 insertions(+), 107 deletions(-) diff --git a/Makefile b/Makefile index 2431614d1..b0f01c49c 100644 --- a/Makefile +++ b/Makefile @@ -25,92 +25,6 @@ verify: cd ${SIM}/sim; ./sim-testfloat-batch all make imperasdv -imperasdv: - iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m - iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m - -imperasdv_cov: - touch ${SIM}/seed0.txt - echo "0" > ${SIM}/seed0.txt -# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --verbose --seed 0 --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m -# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/cov/rv64gc_arch64i.ucdb --verbose -# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose - run-elf-cov.bash --elf ${WALLY}/tests/riscvdv/asm_test/riscv_arithmetic_basic_test_0.elf --seed ${SIM}/questa/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose - vcover report -details -html ${SIM}/questa/riscv.ucdb - -funcovreg: - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m --cover - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/I --cover - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege --cover - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/Q --cover - rm -f ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/*/src/*/dut/my.elf - iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I --cover - vcover report -details -html ${SIM}/questa/riscv.ucdb - - - -# test_name=riscv_arithmetic_basic_test -riscvdv: - python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gen,gcc_compile >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1 -# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gcc_compile >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1 -# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps iss_sim >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1 -# run-elf.bash --seed ${SIM}/questa/seed0.txt --verbose --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1 - #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/riscv.ucdb --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/functcov_logs/${test_name}.log 2>&1 - #cp ${SIM}/questa/riscv.ucdb ${SIM}/questa/functcov_ucdbs/${test_name}.ucdb - -riscvdv_functcov: - mkdir -p ${SIM}/questa/functcov_logs - mkdir -p ${SIM}/questa/functcov_ucdbs - cd ${SIM}/questa/functcov_logs && rm -rf * - cd ${SIM}/questa/functcov_ucdbs && rm -rf * - make riscvdv test_name=riscv_arithmetic_basic_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_amo_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_ebreak_debug_mode_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_ebreak_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_floating_point_arithmetic_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_floating_point_mmu_stress_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_floating_point_rand_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_full_interrupt_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_hint_instr_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_illegal_instr_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_invalid_csr_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_jump_stress_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_loop_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_machine_mode_rand_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_mmu_stress_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_no_fence_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_non_compressed_instr_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_pmp_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_privileged_mode_rand_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_rand_instr_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_rand_jump_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_sfence_exception_test >> ${SIM}/questa/functcov.log 2>&1 - make riscvdv test_name=riscv_unaligned_load_store_test >> ${SIM}/questa/functcov.log 2>&1 - -combine_functcov: - mkdir -p ${SIM}/questa/functcov - mkdir -p ${SIM}/questa/functcov_logs - cd ${SIM}/questa/functcov && rm -rf * - wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf > ${SIM}/questa/functcov_logs/add.log 2>&1 - - #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 - #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 - #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/functcov/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/functcov_logs/add.log 2>&1 - - vcover merge ${SIM}/questa/functcov/functcov.ucdb ${SIM}/questa/functcov/*.ucdb ${SIM}/questa/functcov_ucdbs/* -suppress 6854 -64 - # vcover merge ${SIM}/questa/functcov/functcov.ucdb ${SIM}/questa/functcov_ucdbs/* -suppress 6854 -64 - vcover report -details -html ${SIM}/questa/functcov/functcov.ucdb - vcover report ${SIM}/questa/functcov/functcov.ucdb -details -cvg > ${SIM}/questa/functcov/functcov.log - vcover report ${SIM}/questa/functcov/functcov.ucdb -testdetails -cvg > ${SIM}/questa/functcov/functcov.testdetails.log -# vcover report ${SIM}/questa/functcov/functcov.ucdb -details -cvg -below 100 | egrep "Coverpoint|Covergroup|Cross" | grep -v Metric > ${SIM}/questa/functcov/functcov.ucdb.summary.log - vcover report ${SIM}/questa/functcov/functcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/functcov/functcov.summary.log - grep "Total Coverage By Instance" ${SIM}/questa/functcov/functcov.ucdb.log - -remove_functcov_artifacts: - rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/functcov.log ${SIM}/questa/covhtmlreport/ ${SIM}/questa/functcov_logs/ ${SIM}/questa/functcov_ucdbs/ ${SIM}/questa/functcov/ -rf - -collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov - benchmarks: make coremark make embench diff --git a/bin/wsim b/bin/wsim index f5c297067..8d9ba3167 100755 --- a/bin/wsim +++ b/bin/wsim @@ -93,7 +93,7 @@ if (args.fcov): # create the output sub-directories. regressionDir = WALLY + '/sim/' -for d in ["logs", "wkdir", "cov", "ucdb"]: +for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb"]: try: os.mkdir(regressionDir+args.sim+"/"+d) except: diff --git a/sim/Makefile b/sim/Makefile index e8fe3c860..9ce1b5c49 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -1,19 +1,10 @@ +# David_Harris@hmc.edu 15 July 2024 +# Simulation Makefile for CORE-V-Wally +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +SIM = ${WALLY}/sim all: riscoftests memfiles coveragetests deriv - # *** Build old tests/imperas-riscv-tests for now; - # Delete this part when the privileged tests transition over to tests/wally-riscv-arch-test - # DH: 2/27/22 temporarily commented out imperas-riscv-tests because license expired - #make -C ../tests/imperas-riscv-tests --jobs - #make -C ../tests/imperas-riscv-tests XLEN=64 --jobs - # Only compile Imperas tests if they are installed locally. - # They are usually a symlink to $RISCV/imperas-riscv-tests and only - # get compiled there manually during installation - #make -C ../addins/imperas-riscv-tests - #make -C ../addins/imperas-riscv-tests XLEN=64 - #cd ../addins/imperas-riscv-tests; elf2hex.sh - #cd ../addins/imperas-riscv-tests; extractFunctionRadix.sh work/*/*/*.elf.objdump - # Link Linux test vectors - #cd ../tests/linux-testgen/linux-testvectors/;./tvLinker.sh wally-riscv-arch-test: wallyriscoftests memfiles @@ -39,6 +30,85 @@ QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb # vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt vcover report -details -threshH 100 -html questa/ucdb/cov.ucdb + +imperasdv_cov: + touch ${SIM}/seed0.txt + echo "0" > ${SIM}/seed0.txt +# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --verbose --seed 0 --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m +# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/cov/rv64gc_arch64i.ucdb --verbose +# /opt/riscv/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose + run-elf-cov.bash --elf ${WALLY}/tests/riscvdv/asm_test/riscv_arithmetic_basic_test_0.elf --seed ${SIM}/questa/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose + vcover report -details -html ${SIM}/questa/riscv.ucdb + +funcovreg: + #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m --cover + #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/I --cover + #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege --cover + #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/Q --cover + rm -f ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/*/src/*/dut/my.elf + iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I --cover + vcover report -details -html ${SIM}/questa/riscv.ucdb + + +riscvdv: + python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gen,gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps iss_sim >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +# run-elf.bash --seed ${SIM}/questa/seed0.txt --verbose --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 + +riscvdv_functcov: + mkdir -p ${SIM}/questa/fcov_logs + mkdir -p ${SIM}/questa/fcov_ucdbs + cd ${SIM}/questa/fcov_logs && rm -rf * + cd ${SIM}/questa/fcov_ucdbs && rm -rf * + make riscvdv test_name=riscv_arithmetic_basic_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_amo_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_ebreak_debug_mode_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_ebreak_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_floating_point_arithmetic_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_floating_point_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_floating_point_rand_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_full_interrupt_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_hint_instr_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_illegal_instr_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_invalid_csr_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_jump_stress_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_loop_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_machine_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_no_fence_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_non_compressed_instr_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_pmp_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_privileged_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_rand_instr_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_rand_jump_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_sfence_exception_test >> ${SIM}/questa/fcov.log 2>&1 + make riscvdv test_name=riscv_unaligned_load_store_test >> ${SIM}/questa/fcov.log 2>&1 + +combine_functcov: + mkdir -p ${SIM}/questa/fcov + mkdir -p ${SIM}/questa/fcov_logs + cd ${SIM}/questa/fcov && rm -rf * + wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf --fcov > ${SIM}/questa/fcov_logs/add.log 2>&1 + + #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 + #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 + #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 + + vcover merge ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/*.ucdb ${SIM}/questa/fcov_ucdb/* -suppress 6854 -64 + # vcover merge ${SIM}/questa/fcov/fcov.ucdb ${SIM}/questa/fcov_ucdbs/* -suppress 6854 -64 + vcover report -details -html ${SIM}/questa/fcov_ucdb/fcov.ucdb + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg > ${SIM}/questa/fcov/fcov.log + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -testdetails -cvg > ${SIM}/questa/fcov/fcov.testdetails.log +# vcover report ${SIM}/questa/fcov/fcov.ucdb -details -cvg -below 100 | egrep "Coverpoint|Covergroup|Cross" | grep -v Metric > ${SIM}/questa/fcov/fcov.ucdb.summary.log + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/fcov/fcov.summary.log + grep "Total Coverage By Instance" ${SIM}/questa/fcov/fcov.log + +remove_functcov_artifacts: + rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/fcov.log ${SIM}/questa/covhtmlreport/ ${SIM}/questa/fcov_logs/ ${SIM}/questa/fcov_ucdbs/ ${SIM}/questa/fcov/ -rf + +collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov + allclean: clean all clean: diff --git a/sim/questa/wally.do b/sim/questa/wally.do index c3dbc3b0f..54d6a1124 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -57,6 +57,7 @@ set FCdefineCOVER_RV64D "" set FCdefineCOVER_RV64ZICSR "" set FCdefineCOVER_RV64C "" set FCdefineIDV_INCLUDE_TRACE2COV "" +set FCTRACE2COV "" set lockstep 0 # ok this is annoying. vlog, vopt, and vsim are very picky about how arguments are passed. @@ -65,7 +66,7 @@ set lockstep 0 set lockstepvoptstring "" set SVLib "" set SVLibPath "" -#set OtherFlags "" +set OtherFlags "" set ImperasPubInc "" set ImperasPrivInc "" set rvviFiles "" @@ -129,10 +130,11 @@ if {$FunctCoverageIndex >= 0} { set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" set FCdefineCOVER_RV64C "+define+COVER_RV64C" set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" + set FCTRACE2COV "+TRACE2COV_ENABLE=1 +VERBOSE=1" set lst [lreplace $lst $FunctCoverageIndex $FunctCoverageIndex] -} - +}\ + set LockStepIndex [lsearch -exact $lst "--lockstep"] # ugh. can't have more than 9 arguments passed to vsim. why? I'll have to remove --lockstep when running # functional coverage and imply it. @@ -148,13 +150,14 @@ if {$LockStepIndex >= 0 || $FunctCoverageIndex >= 0} { set idvFiles $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/*.sv set SVLib "-sv_lib" set SVLibPath $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model - #set OtherFlags $env(OTHERFLAGS) + #set OtherFlags $::env(OTHERFLAGS) # not working 7/15/24 dh; this should be the way to pass things like --verbose (Issue 871) if {$LockStepIndex >= 0} { set lst [lreplace $lst $LockStepIndex $LockStepIndex] } } + # separate the +args from the -G parameters foreach otherArg $lst { if {[string index $otherArg 0] eq "+"} { @@ -201,7 +204,7 @@ vopt $accFlag wkdir/${CFG}_${TESTSUITE}.${TESTBENCH} -work ${WKDIR} ${ParamArgs} #vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} ${PlusArgs} -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} +TRACE2COV_ENABLE=1 -suppress 3829 ${CoverageVsimArg} #vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} ${PlusArgs} -fatal 7 ${SVLib} ${SVLibPath} +IDV_TRACE2COV=1 +TRACE2COV_ENABLE=1 -suppress 3829 ${CoverageVsimArg} -vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} $temp0 $temp1 $temp2 $temp3 -fatal 7 ${SVLib} ${SVLibPath} -suppress 3829 ${CoverageVsimArg} +vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} $temp0 $temp1 $temp2 $temp3 -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} ${FCTRACE2COV} -suppress 3829 ${CoverageVsimArg} # vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 # power add generates the logging necessary for said generation. @@ -215,12 +218,17 @@ if { ${GUI} } { } } -if {$ccov || $FunctCoverage} { +if {$ccov} { set UCDB ${WALLY}/sim/questa/ucdb/${CFG}_${TESTSUITE}.ucdb echo "Saving coverage to ${UCDB}" coverage save -instance /testbench/dut/core ${UCDB} } +if {$FunctCoverage} { + set UCDB ${WALLY}/sim/questa/fcov_ucdb/${CFG}_${TESTSUITE}.ucdb + coverage save -onexit ${UCDB} +} + run -all # power off -r /dut/core/* From d86ef9673d8e2aae9f41f469e6a1773e47df74e9 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 15 Jul 2024 15:34:44 -0700 Subject: [PATCH 075/163] More attempts at functional coverage --- sim/Makefile | 4 ++-- sim/questa/wally.do | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sim/Makefile b/sim/Makefile index 9ce1b5c49..5635431ff 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -89,14 +89,14 @@ combine_functcov: mkdir -p ${SIM}/questa/fcov mkdir -p ${SIM}/questa/fcov_logs cd ${SIM}/questa/fcov && rm -rf * + cd ${SIM}/questa/fcov_ucdb && rm -rf * wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf --fcov > ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/ori.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-ori.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 - vcover merge ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/*.ucdb ${SIM}/questa/fcov_ucdb/* -suppress 6854 -64 - # vcover merge ${SIM}/questa/fcov/fcov.ucdb ${SIM}/questa/fcov_ucdbs/* -suppress 6854 -64 + vcover merge ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/*.ucdb -suppress 6854 -64 vcover report -details -html ${SIM}/questa/fcov_ucdb/fcov.ucdb vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg > ${SIM}/questa/fcov/fcov.log vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -testdetails -cvg > ${SIM}/questa/fcov/fcov.testdetails.log diff --git a/sim/questa/wally.do b/sim/questa/wally.do index 54d6a1124..156431bef 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -130,7 +130,7 @@ if {$FunctCoverageIndex >= 0} { set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" set FCdefineCOVER_RV64C "+define+COVER_RV64C" set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" - set FCTRACE2COV "+TRACE2COV_ENABLE=1 +VERBOSE=1" + set FCTRACE2COV "+TRACE2COV_ENABLE=1" set lst [lreplace $lst $FunctCoverageIndex $FunctCoverageIndex] }\ @@ -218,24 +218,24 @@ if { ${GUI} } { } } -if {$ccov} { - set UCDB ${WALLY}/sim/questa/ucdb/${CFG}_${TESTSUITE}.ucdb - echo "Saving coverage to ${UCDB}" - coverage save -instance /testbench/dut/core ${UCDB} -} - if {$FunctCoverage} { set UCDB ${WALLY}/sim/questa/fcov_ucdb/${CFG}_${TESTSUITE}.ucdb coverage save -onexit ${UCDB} } run -all + +if {$ccov} { + set UCDB ${WALLY}/sim/questa/ucdb/${CFG}_${TESTSUITE}.ucdb + echo "Saving coverage to ${UCDB}" + do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration + coverage save -instance /testbench/dut/core ${UCDB} +} + + # power off -r /dut/core/* -# Code coverage exclusions -if {$ccov} { - do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration -} + # These aren't doing anything helpful #profile report -calltree -file wally-calltree.rpt -cutoff 2 From 25f271064f97ec84a171f3d55beec83cc251422b Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Tue, 16 Jul 2024 09:28:05 -0700 Subject: [PATCH 076/163] Fixed slli.uw bug reported by Lee Moore 16 July 2024 --- bin/wsim | 3 +- src/ieu/alu.sv | 6 +- src/ieu/bmu/bitmanipalu.sv | 10 +-- src/ieu/bmu/bmuctrl.sv | 173 +++++++++++++++++++------------------ src/ieu/controller.sv | 12 +-- src/ieu/datapath.sv | 4 +- src/ieu/ieu.sv | 5 +- 7 files changed, 109 insertions(+), 104 deletions(-) diff --git a/bin/wsim b/bin/wsim index 8d9ba3167..34e725707 100755 --- a/bin/wsim +++ b/bin/wsim @@ -47,7 +47,8 @@ elif (args.elf != ""): if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; check if testsuite has a .elf extension and use that instead if (os.path.isfile(args.testsuite)): ElfFile = "+ElfFile=" + os.path.abspath(args.testsuite) - args.testsuite=args.testsuite.rsplit('/', 1)[1] + if ('/' in args.testsuite): + args.testsuite=args.testsuite.rsplit('/', 1)[1] # strip off path if present else: print("ELF file not found: " + args.testsuite) exit(1) diff --git a/src/ieu/alu.sv b/src/ieu/alu.sv index e142de1e7..acd5b025d 100644 --- a/src/ieu/alu.sv +++ b/src/ieu/alu.sv @@ -30,7 +30,7 @@ module alu import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] A, B, // Operands - input logic W64, // W64-type instruction + input logic W64, UW64, // W64/.uw-type instruction input logic SubArith, // Subtraction or arithmetic shift input logic [2:0] ALUSelect, // ALU mux select signal input logic [3:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction @@ -77,7 +77,7 @@ module alu import cvw::*; #(parameter cvw_t P) ( end else assign ZeroCondMaskInvB = CondMaskInvB; // no masking if Zicond is not supported // Shifts (configurable for rotation) - shifter #(P) sh(.A, .Amt(B[P.LOG_XLEN-1:0]), .Right(Funct3[2]), .W64, .SubArith, .Y(Shift), .Rotate(BALUControl[2])); + shifter #(P) sh(.A(CondShiftA), .Amt(B[P.LOG_XLEN-1:0]), .Right(Funct3[2]), .W64, .SubArith, .Y(Shift), .Rotate(BALUControl[2])); // Condition code flags are based on subtraction output Sum = A-B. // Overflow occurs when the numbers being subtracted have the opposite sign @@ -113,7 +113,7 @@ module alu import cvw::*; #(parameter cvw_t P) ( P.ZBKB_SUPPORTED | P.ZBKC_SUPPORTED | P.ZBKX_SUPPORTED | P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED | P.ZKNH_SUPPORTED) begin : bitmanipalu bitmanipalu #(P) balu( - .A, .B, .W64, .BSelect, .ZBBSelect, .BMUActive, + .A, .B, .W64, .UW64, .BSelect, .ZBBSelect, .BMUActive, .Funct3, .Funct7, .Rs2E, .LT,.LTU, .BALUControl, .PreALUResult, .FullResult, .CondMaskB, .CondShiftA, .ALUResult); end else begin diff --git a/src/ieu/bmu/bitmanipalu.sv b/src/ieu/bmu/bitmanipalu.sv index 4caee782a..9bb0905ad 100644 --- a/src/ieu/bmu/bitmanipalu.sv +++ b/src/ieu/bmu/bitmanipalu.sv @@ -30,16 +30,16 @@ module bitmanipalu import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] A, B, // Operands - input logic W64, // W64-type instruction + input logic W64, UW64, // W64/.uw-type instruction input logic [3:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction input logic [3:0] ZBBSelect, // ZBB mux select signal input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform input logic [6:0] Funct7, // Funct7 field for ZKND and ZKNE operations input logic [4:0] Rs2E, // Register source2 for RNUM of ZKNE/ZKND - input logic LT, // less than flag - input logic LTU, // less than unsigned flag + input logic LT, // less than flag + input logic LTU, // less than unsigned flag input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage - input logic BMUActive, // Bit manipulation instruction being executed + input logic BMUActive, // Bit manipulation instruction being executed input logic [P.XLEN-1:0] PreALUResult, // PreALUResult signals input logic [P.XLEN-1:0] FullResult, // FullResult signals output logic [P.XLEN-1:0] CondMaskB, // B is conditionally masked for ZBS instructions @@ -76,7 +76,7 @@ module bitmanipalu import cvw::*; #(parameter cvw_t P) ( // 0-3 bit Pre-Shift Mux if (P.ZBA_SUPPORTED) begin: zbapreshift if (P.XLEN == 64) begin - mux2 #(64) zextmux(A, {{32{1'b0}}, A[31:0]}, W64, CondZextA); + mux2 #(64) zextmux(A, {{32{1'b0}}, A[31:0]}, UW64, CondZextA); end else assign CondZextA = A; assign PreShiftAmt = Funct3[2:1] & {2{PreShift}}; assign CondShiftA = CondZextA << (PreShiftAmt); diff --git a/src/ieu/bmu/bmuctrl.sv b/src/ieu/bmu/bmuctrl.sv index fb4e603c0..d482616ef 100644 --- a/src/ieu/bmu/bmuctrl.sv +++ b/src/ieu/bmu/bmuctrl.sv @@ -36,6 +36,7 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) ( output logic BRegWriteD, // Indicates if it is a R type B instruction in Decode Stage output logic BALUSrcBD, // Indicates if it is an I/IW (non auipc) type B instruction in Decode Stage output logic BW64D, // Indiciates if it is a W type B instruction in Decode Stage + output logic BUW64D, // Indiciates if it is a .uw type B instruction in Decode Stage output logic BSubArithD, // TRUE if ext, clr, andn, orn, xnor instruction in Decode Stage output logic IllegalBitmanipInstrD, // Indicates if it is unrecognized B instruction in Decode Stage // Execute stage control signals @@ -60,7 +61,7 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) ( logic [3:0] BSelectD; // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding in Decode stage logic [3:0] ZBBSelectD; // ZBB mux select signal in Decode stage - `define BMUCTRLW 20 + `define BMUCTRLW 21 logic [`BMUCTRLW-1:0] BMUControlsD; // Main B Instructions Decoder control signals @@ -72,209 +73,209 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) ( // Main Instruction Decoder always_comb begin - // BALUSelect_BSelect_ZBBSelect_BRegWrite_BALUSrcB_BW64_BALUOp_BSubArithD_RotateD_MaskD_PreShiftD_IllegalBitmanipInstrD + // BALUSelect_BSelect_ZBBSelect_BRegWrite_BALUSrcB_BW64_BUW64_BALUOp_BSubArithD_RotateD_MaskD_PreShiftD_IllegalBitmanipInstrD BMUControlsD = `BMUCTRLW'b000_00_000_0_0_0_0_0_0_0_0_1; // default: Illegal bmu instruction; if (P.ZBA_SUPPORTED) begin casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_0_0_0_1_0; // sh1add - 17'b0110011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_0_0_0_1_0; // sh2add - 17'b0110011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_0_0_0_1_0; // sh3add + 17'b0110011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_0_1_0_0_0_1_0; // sh1add + 17'b0110011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_0_1_0_0_0_1_0; // sh2add + 17'b0110011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_0_1_0_0_0_1_0; // sh3add endcase if (P.XLEN==64) casez({OpD, Funct7D, Funct3D}) - 17'b0111011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_1_0; // sh1add.uw - 17'b0111011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_1_0; // sh2add.uw - 17'b0111011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_1_0; // sh3add.uw - 17'b0111011_0000100_000: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_1_1_0_0_0_0_0; // add.uw - 17'b0011011_000010?_001: BMUControlsD = `BMUCTRLW'b001_0001_0000_1_1_1_1_0_0_0_0_0; // slli.uw + 17'b0111011_0010000_010: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_1_0; // sh1add.uw + 17'b0111011_0010000_100: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_1_0; // sh2add.uw + 17'b0111011_0010000_110: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_1_0; // sh3add.uw + 17'b0111011_0000100_000: BMUControlsD = `BMUCTRLW'b000_0001_0000_1_0_0_1_1_0_0_0_0_0; // add.uw + 17'b0011011_000010?_001: BMUControlsD = `BMUCTRLW'b001_0001_0000_1_1_0_1_1_0_0_0_0_0; // slli.uw endcase end if (P.ZBB_SUPPORTED) begin casez({OpD, Funct7D, Funct3D}) 17'b0010011_0110000_001: if ((Rs2D[4:1] == 4'b0010)) - BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_1_0_0_0_0_0; // sign extend instruction + BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_0_1_0_0_0_0_0; // sign extend instruction else if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0])) - BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_0_1_0_0_0_0_0; // count instruction + BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_0_0_1_0_0_0_0_0; // count instruction 17'b0010011_0010100_101: if (Rs2D[4:0] == 5'b00111) - BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_1_0_0_0_0_0; // orc.b - 17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_1_1_0_0_0_0; // max - 17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_1_1_0_0_0_0; // maxu - 17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_1_1_0_0_0_0; // min - 17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_1_1_0_0_0_0; // minu + BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_0_1_0_0_0_0_0; // orc.b + 17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_0_1_1_0_0_0_0; // max + 17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_0010_0111_1_0_0_0_1_1_0_0_0_0; // maxu + 17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_0_1_1_0_0_0_0; // min + 17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_0010_0011_1_0_0_0_1_1_0_0_0_0; // minu endcase if (P.XLEN==32) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_1_0_0_0_0_0; // zexth (rv32) + 17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_1_0_0_1_0_0_0_0_0; // zexth (rv32) endcase else if (P.XLEN==64) casez({OpD, Funct7D, Funct3D}) - 17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_0_0_1_0_0_0_0_0; // zexth (rv64) + 17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0010_0001_1_0_0_0_1_0_0_0_0_0; // zexth (rv64) 17'b0011011_0110000_001: if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0])) - BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_1_1_0_0_0_0_0; // count word instruction + BMUControlsD = `BMUCTRLW'b000_0010_0000_1_1_1_1_0_0_0_0_0_0; // count word instruction (clzw/ctzw/cpopw) endcase end if (P.ZBC_SUPPORTED) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0000101_010: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_1_0_0_0_0_0; // clmulr - 17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_1_0_0_0_0_0; // clmul/clmulh + 17'b0110011_0000101_010: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_0_1_0_0_0_0_0; // clmulr + 17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_0_1_0_0_0_0_0; // clmul/clmulh endcase if (P.ZBKC_SUPPORTED) begin casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_1_0_0_0_0_0; // clmul/clmulh - // 17'b0110011_0000101_001: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_1_0_0_0_0_0; // clmul - // 17'b0110011_0000101_011: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_1_0_0_0_0_0; // clmulh + 17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_0_1_0_0_0_0_0; // clmul/clmulh + // 17'b0110011_0000101_001: BMUControlsD = `BMUCTRLW'b000_0011_0000_1_0_0_0_1_0_0_0_0_0; // clmul + // 17'b0110011_0000101_011: BMUControlsD = `BMUCTRLW'b000_0011_0001_1_0_0_0_1_0_0_0_0_0; // clmulh endcase end if (P.ZBS_SUPPORTED) begin // ZBS casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_0_0_1_1_0_1_0_0; // bclr - 17'b0110011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_0_0_1_0_0_1_0_0; // bext - 17'b0110011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_0_0_1_0_0_1_0_0; // binv - 17'b0110011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_0_0_1_0_0_1_0_0; // bset + 17'b0110011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_0_0_0_1_1_0_1_0_0; // bclr + 17'b0110011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_0_0_0_1_0_0_1_0_0; // bext + 17'b0110011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_0_0_0_1_0_0_1_0_0; // binv + 17'b0110011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_0_0_0_1_0_0_1_0_0; // bset endcase if (P.XLEN==32) // ZBS 64-bit casez({OpD, Funct7D, Funct3D}) - 17'b0010011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_1_1_0_1_0_0; // bclri - 17'b0010011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_1_0_0_1_0_0; // bexti - 17'b0010011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_1_0_0_1_0_0; // binvi - 17'b0010011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_1_0_0_1_0_0; // bseti + 17'b0010011_0100100_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_0_1_1_0_1_0_0; // bclri + 17'b0010011_0100100_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_0_1_0_0_1_0_0; // bexti + 17'b0010011_0110100_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_0_1_0_0_1_0_0; // binvi + 17'b0010011_0010100_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_0_1_0_0_1_0_0; // bseti endcase else if (P.XLEN==64) // ZBS 64-bit casez({OpD, Funct7D, Funct3D}) - 17'b0010011_010010?_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_1_1_0_1_0_0; // bclri (rv64) - 17'b0010011_010010?_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_1_0_0_1_0_0; // bexti (rv64) - 17'b0010011_011010?_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_1_0_0_1_0_0; // binvi (rv64) - 17'b0010011_001010?_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_1_0_0_1_0_0; // bseti (rv64) + 17'b0010011_010010?_001: BMUControlsD = `BMUCTRLW'b111_0001_0000_1_1_0_0_1_1_0_1_0_0; // bclri (rv64) + 17'b0010011_010010?_101: BMUControlsD = `BMUCTRLW'b101_0001_0000_1_1_0_0_1_0_0_1_0_0; // bexti (rv64) + 17'b0010011_011010?_001: BMUControlsD = `BMUCTRLW'b100_0001_0000_1_1_0_0_1_0_0_1_0_0; // binvi (rv64) + 17'b0010011_001010?_001: BMUControlsD = `BMUCTRLW'b110_0001_0000_1_1_0_0_1_0_0_1_0_0; // bseti (rv64) endcase end if (P.ZBB_SUPPORTED | P.ZBS_SUPPORTED) // rv32i/64i shift instructions need BMU ALUSelect when BMU shifter is used casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_0_1_0_0_0_0_0; // sra, srl, sll - 17'b0010011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_0_1_0_0_0_0_0; // srai, srli, slli - 17'b0111011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_1_1_0_0_0_0_0; // sraw, srlw, sllw - 17'b0011011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_1_1_0_0_0_0_0; // sraiw, srliw, slliw + 17'b0110011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_0_0_1_0_0_0_0_0; // sra, srl, sll + 17'b0010011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_0_0_1_0_0_0_0_0; // srai, srli, slli + 17'b0111011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_0_1_0_1_0_0_0_0_0; // sraw, srlw, sllw + 17'b0011011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_0000_0000_1_1_1_0_1_0_0_0_0_0; // sraiw, srliw, slliw endcase if (P.ZBKB_SUPPORTED) begin // ZBKB Bitmanip casez({OpD,Funct7D, Funct3D}) - 17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_1_0_0_0_0_0; // pack - 17'b0110011_0000100_111: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_1_0_0_0_0_0; // packh + 17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_0_1_0_0_0_0_0; // pack + 17'b0110011_0000100_111: BMUControlsD = `BMUCTRLW'b000_0100_0001_1_0_0_0_1_0_0_0_0_0; // packh 17'b0010011_0110100_101: if (Rs2D == 5'b00111) - BMUControlsD = `BMUCTRLW'b000_0100_0000_1_1_0_1_0_0_0_0_0; // brev8 + BMUControlsD = `BMUCTRLW'b000_0100_0000_1_1_0_0_1_0_0_0_0_0; // brev8 endcase if (P.XLEN==32) casez({OpD, Funct7D, Funct3D}) 17'b0010011_0000100_001: if (Rs2D == 5'b01111) - BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_1_0_0_0_0_0; //zip + BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_0_1_0_0_0_0_0; //zip 17'b0010011_0000100_101: if (Rs2D == 5'b01111) - BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_1_0_0_0_0_0; //unzip + BMUControlsD = `BMUCTRLW'b000_0100_0011_1_1_0_0_1_0_0_0_0_0; //unzip endcase else if (P.XLEN==64) casez({OpD,Funct7D, Funct3D}) - 17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0101_1_0_1_1_0_0_0_0_0; //packw + 17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_0100_0101_1_0_1_0_1_0_0_0_0_0; //packw endcase end if (P.ZBB_SUPPORTED | P.ZBKB_SUPPORTED) begin // ZBB and ZBKB shared instructions casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_1_0_1_0_0_0; // rol - 17'b0110011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_1_0_1_0_0_0; // ror - 17'b0110011_0100000_111: BMUControlsD = `BMUCTRLW'b111_0001_0111_1_0_0_1_1_0_0_0_0; // andn - 17'b0110011_0100000_110: BMUControlsD = `BMUCTRLW'b110_0001_0111_1_0_0_1_1_0_0_0_0; // orn - 17'b0110011_0100000_100: BMUControlsD = `BMUCTRLW'b100_0001_0111_1_0_0_1_1_0_0_0_0; // xnor + 17'b0110011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_0_1_0_1_0_0_0; // rol + 17'b0110011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0001_0111_1_0_0_0_1_0_1_0_0_0; // ror + 17'b0110011_0100000_111: BMUControlsD = `BMUCTRLW'b111_0001_0111_1_0_0_0_1_1_0_0_0_0; // andn + 17'b0110011_0100000_110: BMUControlsD = `BMUCTRLW'b110_0001_0111_1_0_0_0_1_1_0_0_0_0; // orn + 17'b0110011_0100000_100: BMUControlsD = `BMUCTRLW'b100_0001_0111_1_0_0_0_1_1_0_0_0_0; // xnor 17'b0010011_011010?_101: if ((P.XLEN == 32 ^ Funct7D[0]) & (Rs2D == 5'b11000)) - BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_1_0_0_0_0_0; // rev8 + BMUControlsD = `BMUCTRLW'b000_0010_0010_1_1_0_0_1_0_0_0_0_0; // rev8 endcase if (P.XLEN==32) casez({OpD, Funct7D, Funct3D}) - 17'b0010011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_1_0_1_0_0_0; // rori (rv32) + 17'b0010011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_0_1_0_1_0_0_0; // rori (rv32) endcase else if (P.XLEN==64) casez({OpD, Funct7D, Funct3D}) - 17'b0111011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_1_0_1_0_0_0; // rolw - 17'b0111011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_1_0_1_0_0_0; // rorw - 17'b0010011_011000?_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_1_0_1_0_0_0; // rori (rv64) - 17'b0011011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_1_1_0_1_0_0_0; // roriw + 17'b0111011_0110000_001: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_0_1_0_1_0_0_0; // rolw + 17'b0111011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_0_1_0_1_0_1_0_0_0; // rorw + 17'b0010011_011000?_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_0_0_1_0_1_0_0_0; // rori (rv64) + 17'b0011011_0110000_101: BMUControlsD = `BMUCTRLW'b001_0000_0111_1_1_1_0_1_0_1_0_0_0; // roriw endcase end if (P.ZBKX_SUPPORTED) begin //ZBKX casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0010100_100: BMUControlsD = `BMUCTRLW'b000_0110_0000_1_0_0_1_0_0_0_0_0; // xperm8 - 17'b0110011_0010100_010: BMUControlsD = `BMUCTRLW'b000_0110_0001_1_0_0_1_0_0_0_0_0; // xperm4 + 17'b0110011_0010100_100: BMUControlsD = `BMUCTRLW'b000_0110_0000_1_0_0_0_1_0_0_0_0_0; // xperm8 + 17'b0110011_0010100_010: BMUControlsD = `BMUCTRLW'b000_0110_0001_1_0_0_0_1_0_0_0_0_0; // xperm4 endcase end if (P.ZKND_SUPPORTED) begin //ZKND if (P.XLEN==32) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_??10101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_1_0_0_0_0_0; // aes32dsi - final round decrypt - 17'b0110011_??10111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_1_0_0_0_0_0; // aes32dsmi - mid round decrypt + 17'b0110011_??10101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_0_1_0_0_0_0_0; // aes32dsi - final round decrypt + 17'b0110011_??10111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_0_1_0_0_0_0_0; // aes32dsmi - mid round decrypt endcase else if (P.XLEN==64) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0011101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_1_0_0_0_0_0; // aes64ds - decrypt final round - 17'b0110011_0011111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_1_0_0_0_0_0; // aes64dsm - decrypt mid round + 17'b0110011_0011101_000: BMUControlsD = `BMUCTRLW'b000_0111_0100_1_0_0_0_1_0_0_0_0_0; // aes64ds - decrypt final round + 17'b0110011_0011111_000: BMUControlsD = `BMUCTRLW'b000_0111_0000_1_0_0_0_1_0_0_0_0_0; // aes64dsm - decrypt mid round 17'b0010011_0011000_001: if (Rs2D == 5'b00000) - BMUControlsD = `BMUCTRLW'b000_0111_1000_1_1_0_1_0_0_0_0_0; // aes64im - decrypt keyschdule mixcolumns + BMUControlsD = `BMUCTRLW'b000_0111_1000_1_1_0_0_1_0_0_0_0_0; // aes64im - decrypt keyschdule mixcolumns endcase end if (P.ZKNE_SUPPORTED) begin //ZKNE if (P.XLEN==32) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_??10001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_1_0_0_0_0_0; // aes32esi - final round encrypt - 17'b0110011_??10011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_1_0_0_0_0_0; // aes32esmi - mid round encrypt + 17'b0110011_??10001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_0_1_0_0_0_0_0; // aes32esi - final round encrypt + 17'b0110011_??10011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_0_1_0_0_0_0_0; // aes32esmi - mid round encrypt endcase else if (P.XLEN==64) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0011001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_1_0_0_0_0_0; // aes64es - encrypt final round - 17'b0110011_0011011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_1_0_0_0_0_0; // aes64esm - encrypt mid round + 17'b0110011_0011001_000: BMUControlsD = `BMUCTRLW'b000_0111_0101_1_0_0_0_1_0_0_0_0_0; // aes64es - encrypt final round + 17'b0110011_0011011_000: BMUControlsD = `BMUCTRLW'b000_0111_0001_1_0_0_0_1_0_0_0_0_0; // aes64esm - encrypt mid round endcase end if ((P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED) & P.XLEN == 64) begin // ZKND and ZKNE shared instructions casez({OpD, Funct7D, Funct3D}) 17'b0010011_0011000_001: if (Rs2D[4] == 1'b1) - BMUControlsD = `BMUCTRLW'b000_0111_0010_1_0_0_1_0_0_0_0_0; // aes64ks1i - key schedule istr1 - 17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2 + BMUControlsD = `BMUCTRLW'b000_0111_0010_1_0_0_0_1_0_0_0_0_0; // aes64ks1i - key schedule istr1 + 17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2 endcase end if (P.ZKNH_SUPPORTED) begin // ZKNH casez({OpD, Funct7D, Funct3D}) 17'b0010011_0001000_001: - if (Rs2D == 5'b00010) BMUControlsD = `BMUCTRLW'b000_1000_0000_1_0_0_1_0_0_0_0_0; // sha256sig0 - else if (Rs2D == 5'b00011) BMUControlsD = `BMUCTRLW'b000_1000_0001_1_0_0_1_0_0_0_0_0; // sha256sig1 - else if (Rs2D == 5'b00000) BMUControlsD = `BMUCTRLW'b000_1000_0010_1_0_0_1_0_0_0_0_0; // sha256sum0 - else if (Rs2D == 5'b00001) BMUControlsD = `BMUCTRLW'b000_1000_0011_1_0_0_1_0_0_0_0_0; // sha256sum1 + if (Rs2D == 5'b00010) BMUControlsD = `BMUCTRLW'b000_1000_0000_1_0_0_0_1_0_0_0_0_0; // sha256sig0 + else if (Rs2D == 5'b00011) BMUControlsD = `BMUCTRLW'b000_1000_0001_1_0_0_0_1_0_0_0_0_0; // sha256sig1 + else if (Rs2D == 5'b00000) BMUControlsD = `BMUCTRLW'b000_1000_0010_1_0_0_0_1_0_0_0_0_0; // sha256sum0 + else if (Rs2D == 5'b00001) BMUControlsD = `BMUCTRLW'b000_1000_0011_1_0_0_0_1_0_0_0_0_0; // sha256sum1 endcase if (P.XLEN==32) casez({OpD, Funct7D, Funct3D}) - 17'b0110011_0101110_000: BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_1_0_0_0_0_0; // sha512sig0h - 17'b0110011_0101010_000: BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_1_0_0_0_0_0; // sha512sig0l - 17'b0110011_0101111_000: BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_1_0_0_0_0_0; // sha512sig1h - 17'b0110011_0101011_000: BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_1_0_0_0_0_0; // sha512sig1l - 17'b0110011_0101000_000: BMUControlsD = `BMUCTRLW'b000_1000_1100_1_0_0_1_0_0_0_0_0; // sha512sum0r - 17'b0110011_0101001_000: BMUControlsD = `BMUCTRLW'b000_1000_1110_1_0_0_1_0_0_0_0_0; // sha512sum1r + 17'b0110011_0101110_000: BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_0_1_0_0_0_0_0; // sha512sig0h + 17'b0110011_0101010_000: BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_0_1_0_0_0_0_0; // sha512sig0l + 17'b0110011_0101111_000: BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_0_1_0_0_0_0_0; // sha512sig1h + 17'b0110011_0101011_000: BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_0_1_0_0_0_0_0; // sha512sig1l + 17'b0110011_0101000_000: BMUControlsD = `BMUCTRLW'b000_1000_1100_1_0_0_0_1_0_0_0_0_0; // sha512sum0r + 17'b0110011_0101001_000: BMUControlsD = `BMUCTRLW'b000_1000_1110_1_0_0_0_1_0_0_0_0_0; // sha512sum1r endcase else if (P.XLEN==64) casez({OpD, Funct7D, Funct3D}) 17'b0010011_0001000_001: - if (Rs2D == 5'b00110) BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_1_0_0_0_0_0; // sha512sig0 - else if (Rs2D == 5'b00111) BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_1_0_0_0_0_0; // sha512sig1 - else if (Rs2D == 5'b00100) BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_1_0_0_0_0_0; // sha512sum0 - else if (Rs2D == 5'b00101) BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_1_0_0_0_0_0; // sha512sum1 + if (Rs2D == 5'b00110) BMUControlsD = `BMUCTRLW'b000_1000_1000_1_0_0_0_1_0_0_0_0_0; // sha512sig0 + else if (Rs2D == 5'b00111) BMUControlsD = `BMUCTRLW'b000_1000_1001_1_0_0_0_1_0_0_0_0_0; // sha512sig1 + else if (Rs2D == 5'b00100) BMUControlsD = `BMUCTRLW'b000_1000_1010_1_0_0_0_1_0_0_0_0_0; // sha512sum0 + else if (Rs2D == 5'b00101) BMUControlsD = `BMUCTRLW'b000_1000_1011_1_0_0_0_1_0_0_0_0_0; // sha512sum1 endcase end end // Unpack Control Signals - assign {BALUSelectD, BSelectD, ZBBSelectD, BRegWriteD,BALUSrcBD, BW64D, BALUOpD, BSubArithD, RotateD, MaskD, PreShiftD, IllegalBitmanipInstrD} = BMUControlsD; + assign {BALUSelectD, BSelectD, ZBBSelectD, BRegWriteD,BALUSrcBD, BW64D, BUW64D, BALUOpD, BSubArithD, RotateD, MaskD, PreShiftD, IllegalBitmanipInstrD} = BMUControlsD; // Pack BALUControl Signals assign BALUControlD = {RotateD, MaskD, PreShiftD}; diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index 4dbb8ff82..74f5162ba 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -56,7 +56,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( output logic [2:0] Funct3E, // Instruction's funct3 field output logic [6:0] Funct7E, // Instruction's funct7 field output logic IntDivE, // Integer divide - output logic W64E, // RV64 W-type operation + output logic W64E, UW64E, // RV64 W/.uw-type operation output logic SubArithE, // Subtraction or arithmetic shift output logic JumpE, // jump instruction output logic BranchE, // Branch instruction @@ -158,6 +158,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage logic FCvtIntStallD, MDUStallD, CSRRdStallD; // Stall due to conversion, load, multiply/divide, CSR read logic FunctCZeroD; // Funct7 and Funct3 indicate czero.* (not including Op check) + logic BUW64D; // Indiciates if it is a .uw type B instruction in Decode Stage // Extract fields assign OpD = InstrD[6:0]; @@ -326,7 +327,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic BALUSrcBD; // BMU alu src select signal bmuctrl #(P) bmuctrl(.clk, .reset, .InstrD, .ALUOpD, - .BRegWriteD, .BALUSrcBD, .BW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE, + .BRegWriteD, .BALUSrcBD, .BW64D, .BUW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE, .ALUSelectD(PreALUSelectD), .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE); if (P.ZBA_SUPPORTED) begin // ALU Decoding is more comprehensive when ZBA is supported. slt and slti conflicts with sh1add, sh1add.uw @@ -350,6 +351,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign W64D = BaseW64D; assign ALUSrcBD = BaseALUSrcBD; assign SubArithD = BaseSubArithD; // TRUE If B-type or R-type instruction involves inverted operand + assign BUW64D = 1'b0; // no .uw instructions // tie off unused bit manipulation signals assign BSelectE = 4'b0000; @@ -417,9 +419,9 @@ module controller import cvw::*; #(parameter cvw_t P) ( flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); // Execute stage pipeline control register and logic - flopenrc #(44) controlregE(clk, reset, FlushE, ~StallE, - {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, Funct7D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, CZeroD, InstrValidD}, - {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, Funct7E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, CZeroE, InstrValidE}); + flopenrc #(45) controlregE(clk, reset, FlushE, ~StallE, + {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, Funct7D, W64D, BUW64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, CZeroD, InstrValidD}, + {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, Funct7E, W64E, UW64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, CZeroE, InstrValidE}); flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E); flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E); flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE); diff --git a/src/ieu/datapath.sv b/src/ieu/datapath.sv index 12f4204e7..c04d0a4a6 100644 --- a/src/ieu/datapath.sv +++ b/src/ieu/datapath.sv @@ -41,7 +41,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( input logic [6:0] Funct7E, // Funct7 field of instruction in Execute stage input logic StallE, FlushE, // Stall, flush Execute stage input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages - input logic W64E, // W64-type instruction + input logic W64E,UW64E, // W64/.uw-type instruction input logic SubArithE, // Subtraction or arithmetic shift input logic ALUSrcAE, ALUSrcBE, // ALU operands input logic ALUResultSrcE, // Selects result to pass on to Memory stage @@ -109,7 +109,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( comparator #(P.XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE); mux2 #(P.XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE); mux2 #(P.XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE); - alu #(P) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, Funct7E, Rs2E, BALUControlE, BMUActiveE, CZeroE, ALUResultE, IEUAdrE); + alu #(P) alu(SrcAE, SrcBE, W64E, UW64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, Funct7E, Rs2E, BALUControlE, BMUActiveE, CZeroE, ALUResultE, IEUAdrE); mux2 #(P.XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE); mux2 #(P.XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE); diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index 4f9c62cb3..e820a3e41 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -93,6 +93,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( logic [3:0] ZBBSelectE; // ZBB Result Select Signal in Execute Stage logic [2:0] BALUControlE; // ALU Control signals for B instructions in Execute Stage logic SubArithE; // Subtraction or arithmetic shift + logic UW64E; // .uw-type instruction logic [6:0] Funct7E; @@ -111,7 +112,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( .StructuralStallD, .LoadStallD, .StoreStallD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .FlagsE, .FWriteIntE, .PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, - .Funct3E, .Funct7E, .IntDivE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, + .Funct3E, .Funct7E, .IntDivE, .W64E, .UW64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE, .MDUActiveE, .FCvtIntE, .ForwardAE, .ForwardBE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM, .StallM, .FlushM, .MemRWE, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M, @@ -120,7 +121,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( .RdW, .RdE, .RdM); datapath #(P) dp( - .clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .SubArithE, + .clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .UW64E, .SubArithE, .Funct3E, .Funct7E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .JumpE, .BranchSignedE, .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE, .StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW, From 19e9dc5ce0d54f9a07c3345e04419c1aaa439b18 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 16 Jul 2024 15:52:52 -0500 Subject: [PATCH 077/163] Fixed wally.do to correctly log functional coverage. --- sim/questa/wally.do | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sim/questa/wally.do b/sim/questa/wally.do index 156431bef..e5c85b92e 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -58,7 +58,7 @@ set FCdefineCOVER_RV64ZICSR "" set FCdefineCOVER_RV64C "" set FCdefineIDV_INCLUDE_TRACE2COV "" set FCTRACE2COV "" - +set FCdefineIDV_TRACE2COV "" set lockstep 0 # ok this is annoying. vlog, vopt, and vsim are very picky about how arguments are passed. # unforunately it won't allow these to be grouped as one argument per command so they are broken @@ -131,7 +131,7 @@ if {$FunctCoverageIndex >= 0} { set FCdefineCOVER_RV64C "+define+COVER_RV64C" set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" set FCTRACE2COV "+TRACE2COV_ENABLE=1" - + set FCdefineIDV_TRACE2COV "+IDV_TRACE2COV=1" set lst [lreplace $lst $FunctCoverageIndex $FunctCoverageIndex] }\ @@ -196,7 +196,7 @@ set temp3 [lindex $PlusArgs 3] # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${idvFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 +vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals @@ -204,7 +204,7 @@ vopt $accFlag wkdir/${CFG}_${TESTSUITE}.${TESTBENCH} -work ${WKDIR} ${ParamArgs} #vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} ${PlusArgs} -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} +TRACE2COV_ENABLE=1 -suppress 3829 ${CoverageVsimArg} #vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} ${PlusArgs} -fatal 7 ${SVLib} ${SVLibPath} +IDV_TRACE2COV=1 +TRACE2COV_ENABLE=1 -suppress 3829 ${CoverageVsimArg} -vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} $temp0 $temp1 $temp2 $temp3 -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} ${FCTRACE2COV} -suppress 3829 ${CoverageVsimArg} +vsim -lib ${WKDIR} testbenchopt +TEST=${TESTSUITE} $temp0 $temp1 $temp2 $temp3 -fatal 7 ${SVLib} ${SVLibPath} ${OtherFlags} ${FCTRACE2COV} ${FCdefineIDV_TRACE2COV} -suppress 3829 ${CoverageVsimArg} # vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 # power add generates the logging necessary for said generation. From 4d36072f094a2839b8d605a56eeb4db0cb03c5f1 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Wed, 17 Jul 2024 06:04:21 -0700 Subject: [PATCH 078/163] Converted regression-wally to use argparse --- bin/regression-wally | 47 ++++++++++++++++++++++---------------------- bin/wsim | 2 +- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/bin/regression-wally b/bin/regression-wally index a059bf648..8d67e387b 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -11,6 +11,7 @@ # ################################## import sys,os,shutil +import argparse import multiprocessing from collections import namedtuple from multiprocessing import Pool, TimeoutError @@ -320,13 +321,16 @@ coveragesim = "questa" # Questa is required for code/functional coverage #defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready defaultsim = "verilator" # Default simulator for all other tests -ccov = '--ccov' in sys.argv -fp = '--fp' in sys.argv -nightly = '--nightly' in sys.argv -testfloat = '--testfloat' in sys.argv -buildroot = '--buildroot' in sys.argv +parser = argparse.ArgumentParser() +parser.add_argument("--ccov", help="Code Coverage", action="store_true") +parser.add_argument("--fcov", help="Functional Coverage", action="store_true") +parser.add_argument("--nightly", help="Run large nightly regression", action="store_true") +parser.add_argument("--buildroot", help="Include Buildroot Linux boot test (takes many hours, done along with --nightly)", action="store_true") +parser.add_argument("--testfloat", help="Include Testfloat floating-point unit tests", action="store_true") +parser.add_argument("--fp", help="Include floating-point tests in coverage (slower runtime)", action="store_true") +args = parser.parse_args() -if (nightly): +if (args.nightly): nightMode = "--nightly"; # sims = [defaultsim] # uncomment to use only the default simulator sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators @@ -334,7 +338,7 @@ else: nightMode = "" sims = [defaultsim] -if (ccov): # only run RV64GC tests in coverage mode +if (args.ccov): # only run RV64GC tests in coverage mode coverStr = '--ccov' else: coverStr = '' @@ -353,24 +357,24 @@ configs = [ # run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests -if (buildroot): +if (args.buildroot): # addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight -if (ccov): # only run RV64GC tests on Questa in code coverage mode +if (args.ccov): # only run RV64GC tests on Questa in code coverage mode addTests(tests64gc_nofp, "questa") - if (fp): + if (args.fp): addTests(tests64gc_fp, "questa") else: for sim in sims: - if (not (buildroot and sim == defaultsim)): # skip shot buildroot sim if running long one + if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one addTests(tests_buildrootshort, sim) addTests(tests, sim) addTests(tests64gc_nofp, sim) addTests(tests64gc_fp, sim) # run derivative configurations and lockstep tests in nightly regression -if (nightly): +if (args.nightly): addTests(derivconfigtests, defaultsim) sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log" tc = TestCase( @@ -391,9 +395,9 @@ if (nightly): configs.append(tc) # testfloat tests -if (testfloat): # for testfloat alone, just run testfloat tests +if (args.testfloat): # for testfloat alone, just run testfloat tests configs = [] -if (testfloat or nightly): # for nightly, run testfloat along with others +if (args.testfloat or args.nightly): # for nightly, run testfloat along with others testfloatsim = "questa" # change to Verilator when Issue #707 about testfloat not running Verilator is resolved testfloatconfigs = ["fdqh_ieee_rv64gc", "fdq_ieee_rv64gc", "fdh_ieee_rv64gc", "fd_ieee_rv64gc", "fh_ieee_rv64gc", "f_ieee_rv64gc", "fdqh_ieee_rv32gc", "f_ieee_rv32gc"] for config in testfloatconfigs: @@ -458,7 +462,7 @@ if (testfloat or nightly): # for nightly, run testfloat along with others def main(): """Run the tests and count the failures""" - global configs, ccov + global configs, args os.chdir(regressionDir) dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"] for d in dirs: @@ -467,17 +471,12 @@ def main(): os.mkdir(d) except: pass - - if '--makeTests' in sys.argv: - os.chdir(regressionDir) - os.system('./make-tests.sh | tee ./logs/make-tests.log') - - elif '--ccov' in sys.argv: + if args.ccov: TIMEOUT_DUR = 20*60 # seconds os.system('rm -f questa/cov/*.ucdb') - elif '--nightly' in sys.argv: + elif args.nightly in sys.argv: TIMEOUT_DUR = 60*1440 # 1 day - elif '--testfloat' in sys.argv: + elif args.testfloat in sys.argv: TIMEOUT_DUR = 30*60 # seconds else: TIMEOUT_DUR = 10*60 # seconds @@ -497,7 +496,7 @@ def main(): print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR)) # Coverage report - if ccov: + if args.ccov: os.system('make QuestaCodeCoverage') # Count the number of failures if num_fail: diff --git a/bin/wsim b/bin/wsim index 34e725707..b70d0e26f 100755 --- a/bin/wsim +++ b/bin/wsim @@ -27,7 +27,7 @@ parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilat parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") -parser.add_argument("--fcov", "-f", help="Functional Coverage", action="store_true") +parser.add_argument("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true") parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") From df063acf611f0bb2a335fe93ce39a331bab55dee Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 18 Jul 2024 08:26:58 -0700 Subject: [PATCH 079/163] Refactored decompression to use simpler default illegal instruction --- src/ifu/decompress.sv | 190 ++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 120 deletions(-) diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index 512dacfd5..d8a1afb8b 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -32,7 +32,8 @@ module decompress import cvw::*; #(parameter cvw_t P) ( output logic [31:0] InstrD, // Decompressed instruction output logic IllegalCompInstrD // Invalid decompressed instruction ); - + + logic [32:0] LInstrD; // decompressed instruction with illegal flag in [32] logic [15:0] instr16; logic [4:0] rds1, rs2, rs1p, rs2p, rds1p, rdp; logic [11:0] immCILSP, immCILSPD, immCSS, immCSSD, immCL, immCLD, immCI, immCS, immCSD, immCB, immCIASP, immCIW; @@ -75,173 +76,122 @@ module decompress import cvw::*; #(parameter cvw_t P) ( always_comb if (op == 2'b11) begin // noncompressed instruction - InstrD = InstrRawD; - IllegalCompInstrD = '0; + LInstrD = {1'b0, InstrRawD}; end else begin // convert compressed instruction into uncompressed - IllegalCompInstrD = '0; + LInstrD = {1'b1, 16'b0, instr16}; // if a legal instruction is not decoded, default to illegal and preserve 16-bit value for mtval case ({op, instr16[15:13]}) - 5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn - else begin // illegal instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end + 5'b00000: if (immCIW != 0) LInstrD = {1'b0, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn 5'b00001: if (P.ZCD_SUPPORTED) - InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld - else begin // unsupported instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - 5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw - 5'b00011: if (P.XLEN==32) + LInstrD = {1'b0, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld + 5'b00010: LInstrD = {1'b0, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw + 5'b00011: if (P.XLEN==32) begin if (P.ZCF_SUPPORTED) - InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw - else begin - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - else - InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld; + LInstrD = {1'b0, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw + end else + LInstrD = {1'b0, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld 5'b00100: if (P.ZCB_SUPPORTED) if (instr16[12:10] == 3'b000) - InstrD = {10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu + LInstrD = {1'b0, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu else if (instr16[12:10] == 3'b001) begin if (instr16[6]) - InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh + LInstrD = {1'b0, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh else - InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu + LInstrD = {1'b0, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu end else if (instr16[12:10] == 3'b010) - InstrD = {7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb + LInstrD = {1'b0, 7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0) - InstrD = {7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh - else begin - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - else begin - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end + LInstrD = {1'b0, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh 5'b00101: if (P.ZCD_SUPPORTED) - InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd - else begin // unsupported instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - 5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw - 5'b00111: if (P.XLEN==32) + LInstrD = {1'b0, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd + 5'b00110: LInstrD = {1'b0, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw + 5'b00111: if (P.XLEN==32) begin if (P.ZCF_SUPPORTED) - InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw - else begin - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - else - InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd - 5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + LInstrD = {1'b0, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw + end else + LInstrD = {1'b0, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd + 5'b01000: LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi 5'b01001: if (P.XLEN==32) - InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal + LInstrD = {1'b0, immCJ, 5'b00001, 7'b1101111}; // c.jal else - InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw - 5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li + LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw + 5'b01010: LInstrD = {1'b0, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li 5'b01011: if (rds1 != 5'b00010) - InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui + LInstrD = {1'b0, immCILUI, rds1, 7'b0110111}; // c.lui else - InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp + LInstrD = {1'b0, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp 5'b01100: if (instr16[11:10] == 2'b00) - InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli + LInstrD = {1'b0, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli else if (instr16[11:10] == 2'b01) - InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai + LInstrD = {1'b0, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai else if (instr16[11:10] == 2'b10) - InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi + LInstrD = {1'b0, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi else if (instr16[12:10] == 3'b011) if (instr16[6:5] == 2'b00) - InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub + LInstrD = {1'b0, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub else if (instr16[6:5] == 2'b01) - InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor + LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor else if (instr16[6:5] == 2'b10) - InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or + LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or else // if (instr16[6:5] == 2'b11) - InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and + LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and else begin // (instr16[12:10] == 3'b111) if (instr16[6:5] == 2'b00 & P.XLEN > 32) - InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw + LInstrD = {1'b0, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw else if (instr16[6:5] == 2'b01 & P.XLEN > 32) - InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw + LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED) - InstrD = {12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 + LInstrD = {1'b0, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - InstrD = {12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b + LInstrD = {1'b0, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - InstrD = {7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h + LInstrD = {1'b0, 7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - InstrD = {12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h + LInstrD = {1'b0, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED) - InstrD = {12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori + LInstrD = {1'b0, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32) - InstrD = {7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 + LInstrD = {1'b0, 7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED & P.ZMMUL_SUPPORTED) - InstrD = {7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul - else begin // reserved - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - /** end else begin // illegal instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap **/ + LInstrD = {1'b0, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul end - 5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j - 5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz - 5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez - 5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli + 5'b01101: LInstrD = {1'b0, immCJ, 5'b00000, 7'b1101111}; // c.j + 5'b01110: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz + 5'b01111: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez + 5'b10000: LInstrD = {1'b0, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli 5'b10001: if (P.ZCD_SUPPORTED) - InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp - else begin // unsupported instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - 5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp - 5'b10011: if (P.XLEN == 32) + LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + 5'b10010: LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp + 5'b10011: if (P.XLEN == 32) begin if (P.ZCF_SUPPORTED) - InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp - else begin - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - else - InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp + LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp + end else + LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp 5'b10100: if (instr16[12] == 0) if (instr16[6:2] == 5'b00000) - InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr + LInstrD = {1'b0, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr else - InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + LInstrD = {1'b0, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv else if (rs2 == 5'b00000) if (rds1 == 5'b00000) - InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak + LInstrD = {1'b0, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak else - InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr + LInstrD = {1'b0, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr else - InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add + LInstrD = {1'b0, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add 5'b10101: if (P.ZCD_SUPPORTED) - InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp - else begin // unsupported instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - 5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp - 5'b10111: if (P.XLEN==32) + LInstrD = {1'b0, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp + 5'b10110: LInstrD = {1'b0, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp + 5'b10111: if (P.XLEN==32) begin if (P.ZCF_SUPPORTED) - InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp - else begin - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end - else - InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp - default: begin // illegal instruction - IllegalCompInstrD = 1'b1; - InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap - end + LInstrD = {1'b0, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp + end else + LInstrD = {1'b0, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp + default: ; // illegal instruction endcase end + + // extract instruction and illegal from LInstrD + assign {IllegalCompInstrD, InstrD} = LInstrD; + endmodule From 3b4726ea9906cbc943d32b83be98bf0729966f84 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 18 Jul 2024 09:30:16 -0700 Subject: [PATCH 080/163] Check legal compressed nonzero destination registers, add c.nop decoding --- src/ifu/decompress.sv | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index d8a1afb8b..340c5055a 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -109,16 +109,17 @@ module decompress import cvw::*; #(parameter cvw_t P) ( LInstrD = {1'b0, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw end else LInstrD = {1'b0, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd - 5'b01000: LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + 5'b01000: if (rds1 != 5'b0) LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + else if (immCI[5:0] == 6'b0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.nop 5'b01001: if (P.XLEN==32) LInstrD = {1'b0, immCJ, 5'b00001, 7'b1101111}; // c.jal else LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw - 5'b01010: LInstrD = {1'b0, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li - 5'b01011: if (rds1 != 5'b00010) - LInstrD = {1'b0, immCILUI, rds1, 7'b0110111}; // c.lui - else + 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b0, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li + 5'b01011: if (rds1 == 5'b00010) LInstrD = {1'b0, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp + else if (rds1 != 5'b0) + LInstrD = {1'b0, immCILUI, rds1, 7'b0110111}; // c.lui 5'b01100: if (instr16[11:10] == 2'b00) LInstrD = {1'b0, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli else if (instr16[11:10] == 2'b01) @@ -159,25 +160,25 @@ module decompress import cvw::*; #(parameter cvw_t P) ( 5'b01111: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez 5'b10000: LInstrD = {1'b0, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli 5'b10001: if (P.ZCD_SUPPORTED) - LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp - 5'b10010: LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp + if (rds1 != 5'b0) LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp 5'b10011: if (P.XLEN == 32) begin if (P.ZCF_SUPPORTED) LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp end else LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp 5'b10100: if (instr16[12] == 0) - if (instr16[6:2] == 5'b00000) - LInstrD = {1'b0, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr - else + if (instr16[6:2] == 5'b00000) begin + if (rds1 != 5'b0) LInstrD = {1'b0, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr + end else LInstrD = {1'b0, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv else - if (rs2 == 5'b00000) + if (rs2 == 5'b00000) begin if (rds1 == 5'b00000) LInstrD = {1'b0, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak else - LInstrD = {1'b0, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr - else + if (rds1 != 5'b0) LInstrD = {1'b0, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr + end else LInstrD = {1'b0, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add 5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b0, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp From 79d0cb96c2074393efc624dc256cc8dbfb15f14e Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Thu, 18 Jul 2024 18:22:26 -0500 Subject: [PATCH 081/163] Added verilog-ethernet as a submodule. Hoping we can make use of sparse-checkout as there are so many files in this repo. --- .gitmodules | 4 ++++ addins/verilog-ethernet | 1 + 2 files changed, 5 insertions(+) create mode 160000 addins/verilog-ethernet diff --git a/.gitmodules b/.gitmodules index 4717e75eb..4368f3f07 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,7 @@ [submodule "addins/ahbsdc"] path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git +[submodule "addins/verilog-ethernet"] + sparseCheckout = true + path = addins/verilog-ethernet + url = https://github.com/ross144/verilog-ethernet.git diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet new file mode 160000 index 000000000..baac5f8d8 --- /dev/null +++ b/addins/verilog-ethernet @@ -0,0 +1 @@ +Subproject commit baac5f8d811d43853d59d69957975ead8bbed088 From ebea314a6edd238cfff2563f647eeafbd57383e7 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 18 Jul 2024 21:38:17 -0700 Subject: [PATCH 082/163] Modified decompressor to look for illegal x0 values and hints --- src/ifu/decompress.sv | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index 340c5055a..10d59f7f2 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -109,22 +109,27 @@ module decompress import cvw::*; #(parameter cvw_t P) ( LInstrD = {1'b0, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw end else LInstrD = {1'b0, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd - 5'b01000: if (rds1 != 5'b0) LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + 5'b01000: if (rds1 != 5'b0) + if (immCI[5:0] != 0) LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop else if (immCI[5:0] == 6'b0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.nop + else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop 5'b01001: if (P.XLEN==32) LInstrD = {1'b0, immCJ, 5'b00001, 7'b1101111}; // c.jal - else + else if (rds1 != 5'b0) LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b0, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li + else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop 5'b01011: if (rds1 == 5'b00010) LInstrD = {1'b0, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp else if (rds1 != 5'b0) LInstrD = {1'b0, immCILUI, rds1, 7'b0110111}; // c.lui - 5'b01100: if (instr16[11:10] == 2'b00) - LInstrD = {1'b0, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli - else if (instr16[11:10] == 2'b01) - LInstrD = {1'b0, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai - else if (instr16[11:10] == 2'b10) + else if (immCILUI[5:0] != 0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop + 5'b01100: if (instr16[11:10] == 2'b00) begin + if (P.XLEN == 64 | ~immSH[5]) LInstrD = {1'b0, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C + end else if (instr16[11:10] == 2'b01) begin + if (P.XLEN == 64 | ~immSH[5]) LInstrD = {1'b0, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C + end else if (instr16[11:10] == 2'b10) LInstrD = {1'b0, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi else if (instr16[12:10] == 3'b011) if (instr16[6:5] == 2'b00) @@ -158,20 +163,23 @@ module decompress import cvw::*; #(parameter cvw_t P) ( 5'b01101: LInstrD = {1'b0, immCJ, 5'b00000, 7'b1101111}; // c.j 5'b01110: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz 5'b01111: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez - 5'b10000: LInstrD = {1'b0, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli + 5'b10000: if (rds1 != 5'b0) begin + if (P.XLEN == 64 | ~immSH[5]) LInstrD = {1'b0, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C + end else if (immSH != 0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop 5'b10001: if (P.ZCD_SUPPORTED) if (rds1 != 5'b0) LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp 5'b10011: if (P.XLEN == 32) begin if (P.ZCF_SUPPORTED) LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp - end else + end else if (rds1 != 5'b0) LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp 5'b10100: if (instr16[12] == 0) - if (instr16[6:2] == 5'b00000) begin + if (rs2 == 5'b00000) begin if (rds1 != 5'b0) LInstrD = {1'b0, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr end else - LInstrD = {1'b0, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + if (rds1 != 5'b0) LInstrD = {1'b0, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop else if (rs2 == 5'b00000) begin if (rds1 == 5'b00000) @@ -179,7 +187,8 @@ module decompress import cvw::*; #(parameter cvw_t P) ( else if (rds1 != 5'b0) LInstrD = {1'b0, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr end else - LInstrD = {1'b0, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add + if (rds1 != 0) LInstrD = {1'b0, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add + else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL 5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b0, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp 5'b10110: LInstrD = {1'b0, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp From 945722cd5b15a23d2da79a68a9887d26a1681a93 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 18 Jul 2024 22:01:43 -0700 Subject: [PATCH 083/163] Neatly formatted decompress.sv --- src/ifu/decompress.sv | 159 ++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 91 deletions(-) diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index 10d59f7f2..2b0caf269 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -40,6 +40,7 @@ module decompress import cvw::*; #(parameter cvw_t P) ( logic [19:0] immCJ, immCILUI; logic [5:0] immSH; logic [1:0] op; + logic LegalCompInstrD; // Extract op and register source/destination fields assign instr16 = InstrRawD[15:0]; // instruction is already aligned @@ -76,132 +77,108 @@ module decompress import cvw::*; #(parameter cvw_t P) ( always_comb if (op == 2'b11) begin // noncompressed instruction - LInstrD = {1'b0, InstrRawD}; + LInstrD = {1'b1, InstrRawD}; end else begin // convert compressed instruction into uncompressed - LInstrD = {1'b1, 16'b0, instr16}; // if a legal instruction is not decoded, default to illegal and preserve 16-bit value for mtval + LInstrD = {1'b0, 16'b0, instr16}; // if a legal instruction is not decoded, default to illegal and preserve 16-bit value for mtval case ({op, instr16[15:13]}) - 5'b00000: if (immCIW != 0) LInstrD = {1'b0, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn - 5'b00001: if (P.ZCD_SUPPORTED) - LInstrD = {1'b0, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld - 5'b00010: LInstrD = {1'b0, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw + 5'b00000: if (immCIW != 0) LInstrD = {1'b1, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn + 5'b00001: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld + 5'b00010: LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw 5'b00011: if (P.XLEN==32) begin - if (P.ZCF_SUPPORTED) - LInstrD = {1'b0, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw - end else - LInstrD = {1'b0, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw + end else LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld 5'b00100: if (P.ZCB_SUPPORTED) - if (instr16[12:10] == 3'b000) - LInstrD = {1'b0, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu + if (instr16[12:10] == 3'b000) LInstrD = {1'b1, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu else if (instr16[12:10] == 3'b001) begin - if (instr16[6]) - LInstrD = {1'b0, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh - else - LInstrD = {1'b0, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu + if (instr16[6]) LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh + else LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu end else if (instr16[12:10] == 3'b010) - LInstrD = {1'b0, 7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb + LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0) - LInstrD = {1'b0, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh - 5'b00101: if (P.ZCD_SUPPORTED) - LInstrD = {1'b0, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd - 5'b00110: LInstrD = {1'b0, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw + LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh + 5'b00101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd + 5'b00110: LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw 5'b00111: if (P.XLEN==32) begin - if (P.ZCF_SUPPORTED) - LInstrD = {1'b0, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw - end else - LInstrD = {1'b0, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw + end else LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd 5'b01000: if (rds1 != 5'b0) - if (immCI[5:0] != 0) LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi - else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop - else if (immCI[5:0] == 6'b0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.nop - else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop - 5'b01001: if (P.XLEN==32) - LInstrD = {1'b0, immCJ, 5'b00001, 7'b1101111}; // c.jal - else if (rds1 != 5'b0) - LInstrD = {1'b0, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw - 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b0, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li - else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop - 5'b01011: if (rds1 == 5'b00010) - LInstrD = {1'b0, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp - else if (rds1 != 5'b0) - LInstrD = {1'b0, immCILUI, rds1, 7'b0110111}; // c.lui - else if (immCILUI[5:0] != 0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop + if (immCI[5:0] != 0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop + else if (immCI[5:0] == 6'b0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop + 5'b01001: if (P.XLEN==32) LInstrD = {1'b1, immCJ, 5'b00001, 7'b1101111}; // c.jal + else if (rds1 != 5'b0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw + 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b1, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop + 5'b01011: if (rds1 == 5'b00010) LInstrD = {1'b1, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp + else if (rds1 != 5'b0) LInstrD = {1'b1, immCILUI, rds1, 7'b0110111}; // c.lui + else if (immCILUI[5:0] != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop 5'b01100: if (instr16[11:10] == 2'b00) begin - if (P.XLEN == 64 | ~immSH[5]) LInstrD = {1'b0, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C + if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C end else if (instr16[11:10] == 2'b01) begin - if (P.XLEN == 64 | ~immSH[5]) LInstrD = {1'b0, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C - end else if (instr16[11:10] == 2'b10) - LInstrD = {1'b0, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi - else if (instr16[12:10] == 3'b011) - if (instr16[6:5] == 2'b00) - LInstrD = {1'b0, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub - else if (instr16[6:5] == 2'b01) - LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor - else if (instr16[6:5] == 2'b10) - LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or - else // if (instr16[6:5] == 2'b11) - LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and - else begin // (instr16[12:10] == 3'b111) + if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C + end else if (instr16[11:10] == 2'b10) LInstrD = {1'b1, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi + else if (instr16[12:10] == 3'b011) begin + if (instr16[6:5] == 2'b00) LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub + else if (instr16[6:5] == 2'b01) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor + else if (instr16[6:5] == 2'b10) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or + else LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and + end else begin // (instr16[12:10] == 3'b111) if (instr16[6:5] == 2'b00 & P.XLEN > 32) - LInstrD = {1'b0, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw + LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw else if (instr16[6:5] == 2'b01 & P.XLEN > 32) - LInstrD = {1'b0, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw + LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED) - LInstrD = {1'b0, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 + LInstrD = {1'b1, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - LInstrD = {1'b0, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b + LInstrD = {1'b1, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - LInstrD = {1'b0, 7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h + LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - LInstrD = {1'b0, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h + LInstrD = {1'b1, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED) - LInstrD = {1'b0, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori + LInstrD = {1'b1, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32) - LInstrD = {1'b0, 7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 + LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED & P.ZMMUL_SUPPORTED) - LInstrD = {1'b0, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul + LInstrD = {1'b1, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul end - 5'b01101: LInstrD = {1'b0, immCJ, 5'b00000, 7'b1101111}; // c.j - 5'b01110: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz - 5'b01111: LInstrD = {1'b0, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez + 5'b01101: LInstrD = {1'b1, immCJ, 5'b00000, 7'b1101111}; // c.j + 5'b01110: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz + 5'b01111: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez 5'b10000: if (rds1 != 5'b0) begin - if (P.XLEN == 64 | ~immSH[5]) LInstrD = {1'b0, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C - end else if (immSH != 0) LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop + if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C + end else if (immSH != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop 5'b10001: if (P.ZCD_SUPPORTED) - if (rds1 != 5'b0) LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp - 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp + if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp 5'b10011: if (P.XLEN == 32) begin - if (P.ZCF_SUPPORTED) - LInstrD = {1'b0, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp - end else if (rds1 != 5'b0) - LInstrD = {1'b0, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp + end else if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp 5'b10100: if (instr16[12] == 0) if (rs2 == 5'b00000) begin - if (rds1 != 5'b0) LInstrD = {1'b0, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr + if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr end else - if (rds1 != 5'b0) LInstrD = {1'b0, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv - else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop + if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop else if (rs2 == 5'b00000) begin - if (rds1 == 5'b00000) - LInstrD = {1'b0, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak - else - if (rds1 != 5'b0) LInstrD = {1'b0, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr + if (rds1 == 5'b00000) LInstrD = {1'b1, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak + else if (rds1 != 5'b0) LInstrD = {1'b1, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr end else - if (rds1 != 0) LInstrD = {1'b0, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add - else LInstrD = {1'b0, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL - 5'b10101: if (P.ZCD_SUPPORTED) - LInstrD = {1'b0, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp - 5'b10110: LInstrD = {1'b0, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp + if (rds1 != 0) LInstrD = {1'b1, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL + 5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp + 5'b10110: LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp 5'b10111: if (P.XLEN==32) begin - if (P.ZCF_SUPPORTED) - LInstrD = {1'b0, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp - end else - LInstrD = {1'b0, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp + end else LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp default: ; // illegal instruction endcase end // extract instruction and illegal from LInstrD - assign {IllegalCompInstrD, InstrD} = LInstrD; + assign {LegalCompInstrD, InstrD} = LInstrD; + assign IllegalCompInstrD = ~LegalCompInstrD; endmodule From c64c12dc6c469c0349a7e20fc4f11e7f73eeb6db Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 18 Jul 2024 22:48:32 -0700 Subject: [PATCH 084/163] Detect illegal compressed immediates, hints --- src/ifu/decompress.sv | 118 +++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index 2b0caf269..798993d78 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -64,10 +64,10 @@ module decompress import cvw::*; #(parameter cvw_t P) ( assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}}; assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]}; assign immCI = {{7{instr16[12]}}, instr16[6:2]}; - assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; - assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; + assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; // c.lui + assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; // c.addi16sp assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00}; - assign immSH = {instr16[12], instr16[6:2]}; + assign immSH = {instr16[12], instr16[6:2]}; // c. shift instructions: c.srli, c.srai, c.slli // only for RV128 // assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000}; @@ -81,97 +81,99 @@ module decompress import cvw::*; #(parameter cvw_t P) ( end else begin // convert compressed instruction into uncompressed LInstrD = {1'b0, 16'b0, instr16}; // if a legal instruction is not decoded, default to illegal and preserve 16-bit value for mtval case ({op, instr16[15:13]}) - 5'b00000: if (immCIW != 0) LInstrD = {1'b1, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn - 5'b00001: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld - 5'b00010: LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw + 5'b00000: if (immCIW != 0) LInstrD = {1'b1, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn + 5'b00001: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld + 5'b00010: LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw 5'b00011: if (P.XLEN==32) begin - if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw - end else LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw + end else LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld 5'b00100: if (P.ZCB_SUPPORTED) - if (instr16[12:10] == 3'b000) LInstrD = {1'b1, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu + if (instr16[12:10] == 3'b000) LInstrD = {1'b1, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu else if (instr16[12:10] == 3'b001) begin - if (instr16[6]) LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh - else LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu + if (instr16[6]) LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh + else LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu end else if (instr16[12:10] == 3'b010) LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0) LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh - 5'b00101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd - 5'b00110: LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw + 5'b00101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd + 5'b00110: LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw 5'b00111: if (P.XLEN==32) begin - if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw - end else LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw + end else LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; // c.sd 5'b01000: if (rds1 != 5'b0) - if (immCI[5:0] != 0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi - else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop - else if (immCI[5:0] == 6'b0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop - else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop - 5'b01001: if (P.XLEN==32) LInstrD = {1'b1, immCJ, 5'b00001, 7'b1101111}; // c.jal - else if (rds1 != 5'b0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw - 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b1, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li - else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop - 5'b01011: if (rds1 == 5'b00010) LInstrD = {1'b1, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp - else if (rds1 != 5'b0) LInstrD = {1'b1, immCILUI, rds1, 7'b0110111}; // c.lui - else if (immCILUI[5:0] != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop + if (immCI[5:0] != 0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop + else if (immCI[5:0] == 6'b0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop = addi x0, x0, 0 + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop + 5'b01001: if (P.XLEN==32) LInstrD = {1'b1, immCJ, 5'b00001, 7'b1101111}; // c.jal + else if (rds1 != 5'b0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw + 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b1, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop + 5'b01011: if (rds1 == 5'b00010) begin + if (immCIASP[9:4] != 6'b0) LInstrD = {1'b1, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp + end else if (immCILUI[5:0] != 0) + if (rds1 != 5'b0) LInstrD = {1'b1, immCILUI, rds1, 7'b0110111}; // c.lui + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop 5'b01100: if (instr16[11:10] == 2'b00) begin - if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C + if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C end else if (instr16[11:10] == 2'b01) begin - if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C - end else if (instr16[11:10] == 2'b10) LInstrD = {1'b1, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi + if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C + end else if (instr16[11:10] == 2'b10) LInstrD = {1'b1, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi else if (instr16[12:10] == 3'b011) begin - if (instr16[6:5] == 2'b00) LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub - else if (instr16[6:5] == 2'b01) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor - else if (instr16[6:5] == 2'b10) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or - else LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and + if (instr16[6:5] == 2'b00) LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub + else if (instr16[6:5] == 2'b01) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor + else if (instr16[6:5] == 2'b10) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or + else LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and end else begin // (instr16[12:10] == 3'b111) if (instr16[6:5] == 2'b00 & P.XLEN > 32) - LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw + LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw else if (instr16[6:5] == 2'b01 & P.XLEN > 32) - LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw + LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED) - LInstrD = {1'b1, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 + LInstrD = {1'b1, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - LInstrD = {1'b1, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b + LInstrD = {1'b1, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) - LInstrD = {1'b1, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h + LInstrD = {1'b1, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED) - LInstrD = {1'b1, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori + LInstrD = {1'b1, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32) - LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 + LInstrD = {1'b1, 7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED & P.ZMMUL_SUPPORTED) - LInstrD = {1'b1, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul + LInstrD = {1'b1, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul end 5'b01101: LInstrD = {1'b1, immCJ, 5'b00000, 7'b1101111}; // c.j - 5'b01110: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz - 5'b01111: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez + 5'b01110: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz + 5'b01111: LInstrD = {1'b1, immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez 5'b10000: if (rds1 != 5'b0) begin - if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C - end else if (immSH != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop + if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C + end else if (immSH != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop 5'b10001: if (P.ZCD_SUPPORTED) - if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp - 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp + if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp 5'b10011: if (P.XLEN == 32) begin - if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp - end else if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp + end else if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp 5'b10100: if (instr16[12] == 0) if (rs2 == 5'b00000) begin - if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr + if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr end else - if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv - else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop + if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop else if (rs2 == 5'b00000) begin - if (rds1 == 5'b00000) LInstrD = {1'b1, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak - else if (rds1 != 5'b0) LInstrD = {1'b1, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr + if (rds1 == 5'b00000) LInstrD = {1'b1, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak + else if (rds1 != 5'b0) LInstrD = {1'b1, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr end else - if (rds1 != 0) LInstrD = {1'b1, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add - else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL + if (rds1 != 0) LInstrD = {1'b1, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add + else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL 5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp - 5'b10110: LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp + 5'b10110: LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp 5'b10111: if (P.XLEN==32) begin - if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp + if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp end else LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp default: ; // illegal instruction endcase From 34e89e842cc0cda695542b376e8bbcfd72e53eb0 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 19 Jul 2024 11:35:12 -0500 Subject: [PATCH 085/163] Added initial spi code to fpga/zsbl --- fpga/zsbl/spi.c | 24 ++++++++++++++++++++++++ fpga/zsbl/spi.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 fpga/zsbl/spi.c create mode 100644 fpga/zsbl/spi.h diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c new file mode 100644 index 000000000..4c3885fd0 --- /dev/null +++ b/fpga/zsbl/spi.c @@ -0,0 +1,24 @@ +#include "spi.h" + +void write_reg(uintptr_t addr, uint32_t value) { + volatile uint32_t * loc = (volatile uint32_t *) addr; + *loc = value; +} + +// Initialize Sifive FU540 based SPI Controller +void spi_init() { + // Disable interrupts by default + // write_reg(SPI_IE, 0); + + write_reg(SPI_TXMARK, 1); + write_reg(SPI_RXMARK, 0); + + write_reg(SPI_DELAY0, + SIFIVE_SPI_DELAY0_CSSCK(1) | + SIFIVE_SPI_DELAY0_SCKCS(1)); + + write_reg(SPI_DELAY1, + SIFIVE_SPI_DELAY1_INTERCS(1) | + SIFIVE_SPI_DELAY1_INTERXFR(0)); +} + diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h new file mode 100644 index 000000000..97f3d58c3 --- /dev/null +++ b/fpga/zsbl/spi.h @@ -0,0 +1,45 @@ +#pragma once +#ifndef SPI_HEADER +#define SPI_HEADER + +#include <stdint.h> + +/* register offsets */ +#define SPI_SCKDIV 0x00 /* Serial clock divisor */ +#define SPI_SCKMODE 0x04 /* Serial clock mode */ +#define SPI_CSID 0x10 /* Chip select ID */ +#define SPI_CSDEF 0x14 /* Chip select default */ +#define SPI_CSMODE 0x18 /* Chip select mode */ +#define SPI_DELAY0 0x28 /* Delay control 0 */ +#define SPI_DELAY1 0x2c /* Delay control 1 */ +#define SPI_FMT 0x40 /* Frame format */ +#define SPI_TXDATA 0x48 /* Tx FIFO data */ +#define SPI_RXDATA 0x4c /* Rx FIFO data */ +#define SPI_TXMARK 0x50 /* Tx FIFO [<35;39;29Mwatermark */ +#define SPI_RXMARK 0x54 /* Rx FIFO watermark */ + +/* Non-implemented +#define SPI_FCTRL 0x60 // SPI flash interface control +#define SPI_FFMT 0x64 // SPI flash instruction format +*/ +#define SPI_IE 0x70 /* Interrupt Enable Register */ +#define SPI_IP 0x74 /* Interrupt Pendings Register */ + +/* delay0 bits */ +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) + +/* delay1 bits */ +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) + +void write_reg(uintptr_t addr, uint32_t value); +uint32_t read_reg(uintptr_t addr); +void spi_send_byte(uint8_t byte); +void spi_init(); + +#endif From 53b2a51c8967d29a84d83f66a90c72a3b262d590 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 19 Jul 2024 12:30:32 -0500 Subject: [PATCH 086/163] Added tentative spi_send_byte function. --- fpga/zsbl/spi.c | 27 +++++++++++++++++++++++++++ fpga/zsbl/spi.h | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 4c3885fd0..1400b8881 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -5,6 +5,10 @@ void write_reg(uintptr_t addr, uint32_t value) { *loc = value; } +void read_red(uintptr_t addr) { + return *(volatile uint32_t *) addr; +} + // Initialize Sifive FU540 based SPI Controller void spi_init() { // Disable interrupts by default @@ -22,3 +26,26 @@ void spi_init() { SIFIVE_SPI_DELAY1_INTERXFR(0)); } +// Sends and receives a single byte +uint8_t spi_send_byte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); + + /* Not sure how necessary this is. Will keep commented for now. + // Wait a decent amount of time for data to send + for (int i = 0; i < 100; i++) { + __asm__ volatile("nop"); + } + */ + + // Wait for data to come into receive fifo + while (read_reg(SPI_IP) != 2) {} + + // Read received data + result = read_reg(SPI_RXDATA); + + // Return result + return result; +} + + diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index 97f3d58c3..2bd2003c5 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -39,7 +39,7 @@ void write_reg(uintptr_t addr, uint32_t value); uint32_t read_reg(uintptr_t addr); -void spi_send_byte(uint8_t byte); +uint8_t spi_send_byte(uint8_t byte); void spi_init(); #endif From 9c1779a2d5ab986990be71e65e4f1cb3fff50ae0 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 19 Jul 2024 13:11:48 -0500 Subject: [PATCH 087/163] Added some documenation about sparse-checkout for verilog-ethernet submodule. --- addins/README.md | 3 +++ addins/sparse-checkout | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 addins/README.md create mode 100644 addins/sparse-checkout diff --git a/addins/README.md b/addins/README.md new file mode 100644 index 000000000..ba04e05eb --- /dev/null +++ b/addins/README.md @@ -0,0 +1,3 @@ +verilog-ethernet contains many ethernet devices. Wally's synthesizable RVVI interface only requires a small subset of these files. +To do a sparse checkout of this repo copy sparse-checkout to cvw/.git/modules/addins/verilog-ethernet/info +This will make the working directory only contain the necessary files. diff --git a/addins/sparse-checkout b/addins/sparse-checkout new file mode 100644 index 000000000..76eadb284 --- /dev/null +++ b/addins/sparse-checkout @@ -0,0 +1,16 @@ +rtl/eth_mac_mii_fifo.v +rtl/eth_mac_mii.v +rtl/mii_phy_if.v +rtl/ssio_ddr_in.v +rtl/eth_mac_1g.v +rtl/axis_gmii_rx.v +rtl/lfsr.v +rtl/eth_axis_tx.v +rtl/mac_ctrl_tx.v +rtl/axis_gmii_tx.v +rtl/mac_ctrl_rx.v +rtl/mac_pause_ctrl_tx.v +rtl/mac_pause_ctrl_rx.v +lib/axis/rtl/axis_async_fifo_adapter.v +lib/axis/rtl/axis_adapter.v +lib/axis/rtl/axis_async_fifo.v From a324e79b6f1386b856ca0be6eadc894f9d809f68 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 19 Jul 2024 13:12:13 -0500 Subject: [PATCH 088/163] Updated the ethernet frame gap for a faster computer. --- src/rvvi/packetizer.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 1599c28a9..0d33947c1 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -102,7 +102,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); assign CountFlag = RstCount == 32'd100000000; //assign CountFlag = RstCount == 32'd10; - assign DelayFlag = RstCount == 32'd800; + //assign DelayFlag = RstCount == 32'd800; + assign DelayFlag = RstCount == 32'd350; //assign DelayFlag = RstCount == 32'd0; counter #(32) framecounter(m_axi_aclk, ~m_axi_aresetn, (RvviAxiWready & RvviAxiWlast), FrameCount); From ce2cc486424f25d5738d2f195ef6debc6698a8d1 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 19 Jul 2024 13:36:26 -0500 Subject: [PATCH 089/163] Updated verilog-ethernet to be compatible with wally. --- addins/sparse-checkout | 32 ++++++++++++++++---------------- addins/verilog-ethernet | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/addins/sparse-checkout b/addins/sparse-checkout index 76eadb284..f1743725c 100644 --- a/addins/sparse-checkout +++ b/addins/sparse-checkout @@ -1,16 +1,16 @@ -rtl/eth_mac_mii_fifo.v -rtl/eth_mac_mii.v -rtl/mii_phy_if.v -rtl/ssio_ddr_in.v -rtl/eth_mac_1g.v -rtl/axis_gmii_rx.v -rtl/lfsr.v -rtl/eth_axis_tx.v -rtl/mac_ctrl_tx.v -rtl/axis_gmii_tx.v -rtl/mac_ctrl_rx.v -rtl/mac_pause_ctrl_tx.v -rtl/mac_pause_ctrl_rx.v -lib/axis/rtl/axis_async_fifo_adapter.v -lib/axis/rtl/axis_adapter.v -lib/axis/rtl/axis_async_fifo.v +rtl/eth_mac_mii_fifo.sv +rtl/eth_mac_mii.sv +rtl/mii_phy_if.sv +rtl/ssio_ddr_in.sv +rtl/eth_mac_1g.sv +rtl/axis_gmii_rx.sv +rtl/lfsr.sv +rtl/eth_axis_tx.sv +rtl/mac_ctrl_tx.sv +rtl/axis_gmii_tx.sv +rtl/mac_ctrl_rx.sv +rtl/mac_pause_ctrl_tx.sv +rtl/mac_pause_ctrl_rx.sv +lib/axis/rtl/axis_async_fifo_adapter.sv +lib/axis/rtl/axis_adapter.sv +lib/axis/rtl/axis_async_fifo.sv diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet index baac5f8d8..13c33ff1a 160000 --- a/addins/verilog-ethernet +++ b/addins/verilog-ethernet @@ -1 +1 @@ -Subproject commit baac5f8d811d43853d59d69957975ead8bbed088 +Subproject commit 13c33ff1a82348691a40d78cf2bab10cbf4f76b2 From 0d40b8c933d47d33ffe1d3575e143296d4752f72 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 19 Jul 2024 15:48:20 -0500 Subject: [PATCH 090/163] Cleanup in prep to merge the rvvi branch into main. --- addins/sparse-checkout | 1 + addins/verilog-ethernet | 2 +- fpga/constraints/small-debug.xdc | 27 +- fpga/generator/Makefile | 2 + src/rvvi/axis_adapter.sv | 324 ---------- src/rvvi/axis_async_fifo.sv | 909 ---------------------------- src/rvvi/axis_async_fifo_adapter.sv | 377 ------------ src/rvvi/axis_gmii_rx.sv | 357 ----------- src/rvvi/axis_gmii_tx.sv | 457 -------------- src/rvvi/eth_axis_tx.sv | 408 ------------- src/rvvi/eth_mac_1g.sv | 643 -------------------- src/rvvi/eth_mac_mii.sv | 175 ------ src/rvvi/eth_mac_mii_fifo.sv | 339 ----------- src/rvvi/lfsr.sv | 446 -------------- src/rvvi/mac_ctrl_rx.sv | 447 -------------- src/rvvi/mac_ctrl_tx.sv | 420 ------------- src/rvvi/mac_pause_ctrl_rx.sv | 220 ------- src/rvvi/mac_pause_ctrl_tx.sv | 312 ---------- src/rvvi/mii_phy_if.sv | 140 ----- src/rvvi/ssio_ddr_in.sv | 150 ----- src/rvvi/ssio_sdr_in.sv | 166 ----- 21 files changed, 10 insertions(+), 6312 deletions(-) delete mode 100644 src/rvvi/axis_adapter.sv delete mode 100644 src/rvvi/axis_async_fifo.sv delete mode 100644 src/rvvi/axis_async_fifo_adapter.sv delete mode 100644 src/rvvi/axis_gmii_rx.sv delete mode 100644 src/rvvi/axis_gmii_tx.sv delete mode 100644 src/rvvi/eth_axis_tx.sv delete mode 100644 src/rvvi/eth_mac_1g.sv delete mode 100644 src/rvvi/eth_mac_mii.sv delete mode 100644 src/rvvi/eth_mac_mii_fifo.sv delete mode 100644 src/rvvi/lfsr.sv delete mode 100644 src/rvvi/mac_ctrl_rx.sv delete mode 100644 src/rvvi/mac_ctrl_tx.sv delete mode 100644 src/rvvi/mac_pause_ctrl_rx.sv delete mode 100644 src/rvvi/mac_pause_ctrl_tx.sv delete mode 100644 src/rvvi/mii_phy_if.sv delete mode 100644 src/rvvi/ssio_ddr_in.sv delete mode 100644 src/rvvi/ssio_sdr_in.sv diff --git a/addins/sparse-checkout b/addins/sparse-checkout index f1743725c..74cc3f25a 100644 --- a/addins/sparse-checkout +++ b/addins/sparse-checkout @@ -2,6 +2,7 @@ rtl/eth_mac_mii_fifo.sv rtl/eth_mac_mii.sv rtl/mii_phy_if.sv rtl/ssio_ddr_in.sv +rtl/ssio_sdr_in.sv rtl/eth_mac_1g.sv rtl/axis_gmii_rx.sv rtl/lfsr.sv diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet index 13c33ff1a..43990ab4f 160000 --- a/addins/verilog-ethernet +++ b/addins/verilog-ethernet @@ -1 +1 @@ -Subproject commit 13c33ff1a82348691a40d78cf2bab10cbf4f76b2 +Subproject commit 43990ab4fd0c8d34dbc1be5cd8d4f3ed3e33f853 diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index 10d64c126..ce824620b 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -32,30 +32,25 @@ set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe3] +set_property port_width 1 [get_debug_ports u_ila_0/probe3] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] -connect_debug_port u_ila_0/probe3 [get_nets [list {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[0]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[1]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[2]} {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_txd[3]} ]] +connect_debug_port u_ila_0/probe3 [get_nets [list {RvviAxiRlast}]] create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe4] +set_property port_width 1 [get_debug_ports u_ila_0/probe4] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] -connect_debug_port u_ila_0/probe4 [get_nets [list {packetizer/CurrState[0]} {packetizer/CurrState[1]} {packetizer/CurrState[2]} {packetizer/CurrState[3]}]] +connect_debug_port u_ila_0/probe4 [get_nets [list {RvviAxiRvalid}]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe5] +set_property port_width 4 [get_debug_ports u_ila_0/probe5] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] -connect_debug_port u_ila_0/probe5 [get_nets [list {ethernet/eth_mac_1g_mii_inst/mii_phy_if_inst/mac_mii_tx_en} ]] +connect_debug_port u_ila_0/probe5 [get_nets [list {packetizer/CurrState[0]} {packetizer/CurrState[1]} {packetizer/CurrState[2]} {packetizer/CurrState[3]}]] create_debug_port u_ila_0 probe set_property port_width 64 [get_debug_ports u_ila_0/probe6] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] -#create_debug_port u_ila_0 probe -#set_property port_width 1 [get_debug_ports u_ila_0/probe7] -#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] -#connect_debug_port u_ila_0/probe7 [get_nets [list {IlaTrigger} ]] - create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe7] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] @@ -81,16 +76,6 @@ set_property port_width 3 [get_debug_ports u_ila_0/probe11] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] connect_debug_port u_ila_0/probe11 [get_nets [list {triggergen/CurrState[0]} {triggergen/CurrState[1]} {triggergen/CurrState[2]}]] -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe12] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe12] -connect_debug_port u_ila_0/probe12 [get_nets [list {RvviAxiRlast}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe13] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe13] -connect_debug_port u_ila_0/probe13 [get_nets [list {RvviAxiRvalid}]] - # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index df4ed0e2a..c23e22ee0 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -51,6 +51,8 @@ PreProcessFiles: $(MAKE) -C ../../sim deriv rm -rf ../src/CopiedFiles_do_not_add_to_repo/ cp -r ../../src/ ../src/CopiedFiles_do_not_add_to_repo/ + cp -r ../../addins/verilog-ethernet/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi + cp -r ../../addins/verilog-ethernet/*/*/*/*.sv ../src/CopiedFiles_do_not_add_to_repo/rvvi mkdir ../src/CopiedFiles_do_not_add_to_repo/config/ cp ../../config/deriv/fpga/config.vh ../src/CopiedFiles_do_not_add_to_repo/config/ ./insert_debug_comment.sh diff --git a/src/rvvi/axis_adapter.sv b/src/rvvi/axis_adapter.sv deleted file mode 100644 index 8807a03b7..000000000 --- a/src/rvvi/axis_adapter.sv +++ /dev/null @@ -1,324 +0,0 @@ -/* - -Copyright (c) 2014-2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream bus width adapter - */ -module axis_adapter # -( - // Width of input AXI stream interface in bits - parameter S_DATA_WIDTH = 8, - // Propagate tkeep signal on input interface - // If disabled, tkeep assumed to be 1'b1 - parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on input interface - parameter S_KEEP_WIDTH = ((S_DATA_WIDTH+7)/8), - // Width of output AXI stream interface in bits - parameter M_DATA_WIDTH = 8, - // Propagate tkeep signal on output interface - // If disabled, tkeep assumed to be 1'b1 - parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on output interface - parameter M_KEEP_WIDTH = ((M_DATA_WIDTH+7)/8), - // Propagate tid signal - parameter ID_ENABLE = 0, - // tid signal width - parameter ID_WIDTH = 8, - // Propagate tdest signal - parameter DEST_ENABLE = 0, - // tdest signal width - parameter DEST_WIDTH = 8, - // Propagate tuser signal - parameter USER_ENABLE = 1, - // tuser signal width - parameter USER_WIDTH = 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI input - */ - input wire [S_DATA_WIDTH-1:0] s_axis_tdata, - input wire [S_KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI output - */ - output wire [M_DATA_WIDTH-1:0] m_axis_tdata, - output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser -); - -// force keep width to 1 when disabled -localparam S_BYTE_LANES = S_KEEP_ENABLE ? S_KEEP_WIDTH : 1; -localparam M_BYTE_LANES = M_KEEP_ENABLE ? M_KEEP_WIDTH : 1; - -// bus byte sizes (must be identical) -localparam S_BYTE_SIZE = S_DATA_WIDTH / S_BYTE_LANES; -localparam M_BYTE_SIZE = M_DATA_WIDTH / M_BYTE_LANES; - -// bus width assertions -initial begin - if (S_BYTE_SIZE * S_BYTE_LANES != S_DATA_WIDTH) begin - $error("Error: input data width not evenly divisible (instance %m)"); - $finish; - end - - if (M_BYTE_SIZE * M_BYTE_LANES != M_DATA_WIDTH) begin - $error("Error: output data width not evenly divisible (instance %m)"); - $finish; - end - - if (S_BYTE_SIZE != M_BYTE_SIZE) begin - $error("Error: byte size mismatch (instance %m)"); - $finish; - end -end - -generate - -if (M_BYTE_LANES == S_BYTE_LANES) begin : bypass - // same width; bypass - - assign s_axis_tready = m_axis_tready; - - assign m_axis_tdata = s_axis_tdata; - assign m_axis_tkeep = M_KEEP_ENABLE ? s_axis_tkeep : {M_KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid = s_axis_tvalid; - assign m_axis_tlast = s_axis_tlast; - assign m_axis_tid = ID_ENABLE ? s_axis_tid : {ID_WIDTH{1'b0}}; - assign m_axis_tdest = DEST_ENABLE ? s_axis_tdest : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser = USER_ENABLE ? s_axis_tuser : {USER_WIDTH{1'b0}}; - -end else if (M_BYTE_LANES > S_BYTE_LANES) begin : upsize - // output is wider; upsize - - // required number of segments in wider bus - localparam SEG_COUNT = M_BYTE_LANES / S_BYTE_LANES; - // data width and keep width per segment - localparam SEG_DATA_WIDTH = M_DATA_WIDTH / SEG_COUNT; - localparam SEG_KEEP_WIDTH = M_BYTE_LANES / SEG_COUNT; - - reg [$clog2(SEG_COUNT)-1:0] seg_reg = 0; - - reg [S_DATA_WIDTH-1:0] s_axis_tdata_reg = {S_DATA_WIDTH{1'b0}}; - reg [S_KEEP_WIDTH-1:0] s_axis_tkeep_reg = {S_KEEP_WIDTH{1'b0}}; - reg s_axis_tvalid_reg = 1'b0; - reg s_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] s_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] s_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] s_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - reg [M_DATA_WIDTH-1:0] m_axis_tdata_reg = {M_DATA_WIDTH{1'b0}}; - reg [M_KEEP_WIDTH-1:0] m_axis_tkeep_reg = {M_KEEP_WIDTH{1'b0}}; - reg m_axis_tvalid_reg = 1'b0; - reg m_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - assign s_axis_tready = !s_axis_tvalid_reg; - - assign m_axis_tdata = m_axis_tdata_reg; - assign m_axis_tkeep = M_KEEP_ENABLE ? m_axis_tkeep_reg : {M_KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid = m_axis_tvalid_reg; - assign m_axis_tlast = m_axis_tlast_reg; - assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; - assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - - always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready; - - if (!m_axis_tvalid_reg || m_axis_tready) begin - // output register empty - - if (seg_reg == 0) begin - m_axis_tdata_reg[seg_reg*SEG_DATA_WIDTH +: SEG_DATA_WIDTH] <= s_axis_tvalid_reg ? s_axis_tdata_reg : s_axis_tdata; - m_axis_tkeep_reg <= s_axis_tvalid_reg ? s_axis_tkeep_reg : s_axis_tkeep; - end else begin - m_axis_tdata_reg[seg_reg*SEG_DATA_WIDTH +: SEG_DATA_WIDTH] <= s_axis_tdata; - m_axis_tkeep_reg[seg_reg*SEG_KEEP_WIDTH +: SEG_KEEP_WIDTH] <= s_axis_tkeep; - end - m_axis_tlast_reg <= s_axis_tvalid_reg ? s_axis_tlast_reg : s_axis_tlast; - m_axis_tid_reg <= s_axis_tvalid_reg ? s_axis_tid_reg : s_axis_tid; - m_axis_tdest_reg <= s_axis_tvalid_reg ? s_axis_tdest_reg : s_axis_tdest; - m_axis_tuser_reg <= s_axis_tvalid_reg ? s_axis_tuser_reg : s_axis_tuser; - - if (s_axis_tvalid_reg) begin - // consume data from buffer - s_axis_tvalid_reg <= 1'b0; - - if (s_axis_tlast_reg || seg_reg == SEG_COUNT-1) begin - seg_reg <= 0; - m_axis_tvalid_reg <= 1'b1; - end else begin - seg_reg <= seg_reg + 1; - end - end else if (s_axis_tvalid) begin - // data direct from input - if (s_axis_tlast || seg_reg == SEG_COUNT-1) begin - seg_reg <= 0; - m_axis_tvalid_reg <= 1'b1; - end else begin - seg_reg <= seg_reg + 1; - end - end - end else if (s_axis_tvalid && s_axis_tready) begin - // store input data in skid buffer - s_axis_tdata_reg <= s_axis_tdata; - s_axis_tkeep_reg <= s_axis_tkeep; - s_axis_tvalid_reg <= 1'b1; - s_axis_tlast_reg <= s_axis_tlast; - s_axis_tid_reg <= s_axis_tid; - s_axis_tdest_reg <= s_axis_tdest; - s_axis_tuser_reg <= s_axis_tuser; - end - - if (rst) begin - seg_reg <= 0; - s_axis_tvalid_reg <= 1'b0; - m_axis_tvalid_reg <= 1'b0; - end - end - -end else begin : downsize - // output is narrower; downsize - - // required number of segments in wider bus - localparam SEG_COUNT = S_BYTE_LANES / M_BYTE_LANES; - // data width and keep width per segment - localparam SEG_DATA_WIDTH = S_DATA_WIDTH / SEG_COUNT; - localparam SEG_KEEP_WIDTH = S_BYTE_LANES / SEG_COUNT; - - reg [S_DATA_WIDTH-1:0] s_axis_tdata_reg = {S_DATA_WIDTH{1'b0}}; - reg [S_KEEP_WIDTH-1:0] s_axis_tkeep_reg = {S_KEEP_WIDTH{1'b0}}; - reg s_axis_tvalid_reg = 1'b0; - reg s_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] s_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] s_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] s_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - reg [M_DATA_WIDTH-1:0] m_axis_tdata_reg = {M_DATA_WIDTH{1'b0}}; - reg [M_KEEP_WIDTH-1:0] m_axis_tkeep_reg = {M_KEEP_WIDTH{1'b0}}; - reg m_axis_tvalid_reg = 1'b0; - reg m_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - assign s_axis_tready = !s_axis_tvalid_reg; - - assign m_axis_tdata = m_axis_tdata_reg; - assign m_axis_tkeep = M_KEEP_ENABLE ? m_axis_tkeep_reg : {M_KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid = m_axis_tvalid_reg; - assign m_axis_tlast = m_axis_tlast_reg; - assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; - assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - - always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready; - - if (!m_axis_tvalid_reg || m_axis_tready) begin - // output register empty - - m_axis_tdata_reg <= s_axis_tvalid_reg ? s_axis_tdata_reg : s_axis_tdata; - m_axis_tkeep_reg <= s_axis_tvalid_reg ? s_axis_tkeep_reg : s_axis_tkeep; - m_axis_tlast_reg <= 1'b0; - m_axis_tid_reg <= s_axis_tvalid_reg ? s_axis_tid_reg : s_axis_tid; - m_axis_tdest_reg <= s_axis_tvalid_reg ? s_axis_tdest_reg : s_axis_tdest; - m_axis_tuser_reg <= s_axis_tvalid_reg ? s_axis_tuser_reg : s_axis_tuser; - - if (s_axis_tvalid_reg) begin - // buffer has data; shift out from buffer - s_axis_tdata_reg <= s_axis_tdata_reg >> SEG_DATA_WIDTH; - s_axis_tkeep_reg <= s_axis_tkeep_reg >> SEG_KEEP_WIDTH; - - m_axis_tvalid_reg <= 1'b1; - - if ((s_axis_tkeep_reg >> SEG_KEEP_WIDTH) == 0) begin - s_axis_tvalid_reg <= 1'b0; - m_axis_tlast_reg <= s_axis_tlast_reg; - end - end else if (s_axis_tvalid && s_axis_tready) begin - // buffer is empty; store from input - s_axis_tdata_reg <= s_axis_tdata >> SEG_DATA_WIDTH; - s_axis_tkeep_reg <= s_axis_tkeep >> SEG_KEEP_WIDTH; - s_axis_tlast_reg <= s_axis_tlast; - s_axis_tid_reg <= s_axis_tid; - s_axis_tdest_reg <= s_axis_tdest; - s_axis_tuser_reg <= s_axis_tuser; - - m_axis_tvalid_reg <= 1'b1; - - if ((s_axis_tkeep >> SEG_KEEP_WIDTH) == 0) begin - s_axis_tvalid_reg <= 1'b0; - m_axis_tlast_reg <= s_axis_tlast; - end else begin - s_axis_tvalid_reg <= 1'b1; - end - end - end else if (s_axis_tvalid && s_axis_tready) begin - // store input data - s_axis_tdata_reg <= s_axis_tdata; - s_axis_tkeep_reg <= s_axis_tkeep; - s_axis_tvalid_reg <= 1'b1; - s_axis_tlast_reg <= s_axis_tlast; - s_axis_tid_reg <= s_axis_tid; - s_axis_tdest_reg <= s_axis_tdest; - s_axis_tuser_reg <= s_axis_tuser; - end - - if (rst) begin - s_axis_tvalid_reg <= 1'b0; - m_axis_tvalid_reg <= 1'b0; - end - end - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/axis_async_fifo.sv b/src/rvvi/axis_async_fifo.sv deleted file mode 100644 index 1d8b6244f..000000000 --- a/src/rvvi/axis_async_fifo.sv +++ /dev/null @@ -1,909 +0,0 @@ -/* - -Copyright (c) 2014-2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream asynchronous FIFO - */ -module axis_async_fifo # -( - // FIFO depth in words - // KEEP_WIDTH words per cycle if KEEP_ENABLE set - // Rounded up to nearest power of 2 cycles - parameter DEPTH = 4096, - // Width of AXI stream interfaces in bits - parameter DATA_WIDTH = 8, - // Propagate tkeep signal - // If disabled, tkeep assumed to be 1'b1 - parameter KEEP_ENABLE = (DATA_WIDTH>8), - // tkeep signal width (words per cycle) - parameter KEEP_WIDTH = ((DATA_WIDTH+7)/8), - // Propagate tlast signal - parameter LAST_ENABLE = 1, - // Propagate tid signal - parameter ID_ENABLE = 0, - // tid signal width - parameter ID_WIDTH = 8, - // Propagate tdest signal - parameter DEST_ENABLE = 0, - // tdest signal width - parameter DEST_WIDTH = 8, - // Propagate tuser signal - parameter USER_ENABLE = 1, - // tuser signal width - parameter USER_WIDTH = 1, - // number of RAM pipeline registers - parameter RAM_PIPELINE = 1, - // use output FIFO - // When set, the RAM read enable and pipeline clock enables are removed - parameter OUTPUT_FIFO_ENABLE = 0, - // Frame FIFO mode - operate on frames instead of cycles - // When set, m_axis_tvalid will not be deasserted within a frame - // Requires LAST_ENABLE set - parameter FRAME_FIFO = 0, - // tuser value for bad frame marker - parameter USER_BAD_FRAME_VALUE = 1'b1, - // tuser mask for bad frame marker - parameter USER_BAD_FRAME_MASK = 1'b1, - // Drop frames larger than FIFO - // Requires FRAME_FIFO set - parameter DROP_OVERSIZE_FRAME = FRAME_FIFO, - // Drop frames marked bad - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_BAD_FRAME = 0, - // Drop incoming frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_WHEN_FULL = 0, - // Mark incoming frames as bad frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO to be clear - parameter MARK_WHEN_FULL = 0, - // Enable pause request input - parameter PAUSE_ENABLE = 0, - // Pause between frames - parameter FRAME_PAUSE = FRAME_FIFO -) -( - /* - * AXI input - */ - input wire s_clk, - input wire s_rst, - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI output - */ - input wire m_clk, - input wire m_rst, - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * Pause - */ - input wire s_pause_req, - output wire s_pause_ack, - input wire m_pause_req, - output wire m_pause_ack, - - /* - * Status - */ - output wire [$clog2(DEPTH):0] s_status_depth, - output wire [$clog2(DEPTH):0] s_status_depth_commit, - output wire s_status_overflow, - output wire s_status_bad_frame, - output wire s_status_good_frame, - output wire [$clog2(DEPTH):0] m_status_depth, - output wire [$clog2(DEPTH):0] m_status_depth_commit, - output wire m_status_overflow, - output wire m_status_bad_frame, - output wire m_status_good_frame -); - -parameter ADDR_WIDTH = (KEEP_ENABLE && KEEP_WIDTH > 1) ? $clog2(DEPTH/KEEP_WIDTH) : $clog2(DEPTH); - -parameter OUTPUT_FIFO_ADDR_WIDTH = RAM_PIPELINE < 2 ? 3 : $clog2(RAM_PIPELINE*2+7); - -// check configuration -initial begin - if (FRAME_FIFO && !LAST_ENABLE) begin - $error("Error: FRAME_FIFO set requires LAST_ENABLE set (instance %m)"); - $finish; - end - - if (DROP_OVERSIZE_FRAME && !FRAME_FIFO) begin - $error("Error: DROP_OVERSIZE_FRAME set requires FRAME_FIFO set (instance %m)"); - $finish; - end - - if (DROP_BAD_FRAME && !(FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin - $error("Error: DROP_BAD_FRAME set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)"); - $finish; - end - - if (DROP_WHEN_FULL && !(FRAME_FIFO && DROP_OVERSIZE_FRAME)) begin - $error("Error: DROP_WHEN_FULL set requires FRAME_FIFO and DROP_OVERSIZE_FRAME set (instance %m)"); - $finish; - end - - if ((DROP_BAD_FRAME || MARK_WHEN_FULL) && (USER_BAD_FRAME_MASK & {USER_WIDTH{1'b1}}) == 0) begin - $error("Error: Invalid USER_BAD_FRAME_MASK value (instance %m)"); - $finish; - end - - if (MARK_WHEN_FULL && FRAME_FIFO) begin - $error("Error: MARK_WHEN_FULL is not compatible with FRAME_FIFO (instance %m)"); - $finish; - end - - if (MARK_WHEN_FULL && !LAST_ENABLE) begin - $error("Error: MARK_WHEN_FULL set requires LAST_ENABLE set (instance %m)"); - $finish; - end -end - -localparam KEEP_OFFSET = DATA_WIDTH; -localparam LAST_OFFSET = KEEP_OFFSET + (KEEP_ENABLE ? KEEP_WIDTH : 0); -localparam ID_OFFSET = LAST_OFFSET + (LAST_ENABLE ? 1 : 0); -localparam DEST_OFFSET = ID_OFFSET + (ID_ENABLE ? ID_WIDTH : 0); -localparam USER_OFFSET = DEST_OFFSET + (DEST_ENABLE ? DEST_WIDTH : 0); -localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0); - -function [ADDR_WIDTH:0] bin2gray(input [ADDR_WIDTH:0] b); - bin2gray = b ^ (b >> 1); -endfunction - -function [ADDR_WIDTH:0] gray2bin(input [ADDR_WIDTH:0] g); - integer i; - for (i = 0; i <= ADDR_WIDTH; i = i + 1) begin - gray2bin[i] = ^(g >> i); - end -endfunction - -reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_commit_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_sync_commit_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] wr_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; -reg [ADDR_WIDTH:0] rd_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; - -reg [ADDR_WIDTH:0] wr_ptr_temp; -reg [ADDR_WIDTH:0] rd_ptr_temp; - -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] wr_ptr_commit_sync_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}}; -(* SHREG_EXTRACT = "NO" *) -reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}}; - -reg wr_ptr_update_valid_reg = 1'b0; -reg wr_ptr_update_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_sync1_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_sync2_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_sync3_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_ack_sync1_reg = 1'b0; -(* SHREG_EXTRACT = "NO" *) -reg wr_ptr_update_ack_sync2_reg = 1'b0; - -(* SHREG_EXTRACT = "NO" *) -reg s_rst_sync1_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg s_rst_sync2_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg s_rst_sync3_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg m_rst_sync1_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg m_rst_sync2_reg = 1'b1; -(* SHREG_EXTRACT = "NO" *) -reg m_rst_sync3_reg = 1'b1; - -(* ramstyle = "no_rw_check" *) -reg [WIDTH-1:0] mem[(2**ADDR_WIDTH)-1:0]; -reg mem_read_data_valid_reg = 1'b0; - -(* shreg_extract = "no" *) -reg [WIDTH-1:0] m_axis_pipe_reg[RAM_PIPELINE+1-1:0]; -reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0; - -// full when first TWO MSBs do NOT match, but rest matches -// (gray code equivalent of first MSB different but rest same) -wire full = wr_ptr_gray_reg == (rd_ptr_gray_sync2_reg ^ {2'b11, {ADDR_WIDTH-1{1'b0}}}); -// empty when pointers match exactly -wire empty = FRAME_FIFO ? (rd_ptr_reg == wr_ptr_commit_sync_reg) : (rd_ptr_gray_reg == wr_ptr_gray_sync2_reg); -// overflow within packet -wire full_wr = wr_ptr_reg == (wr_ptr_commit_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}}); - -// control signals -reg write; -reg read; -reg store_output; - -reg s_frame_reg = 1'b0; -reg m_frame_reg = 1'b0; - -reg drop_frame_reg = 1'b0; -reg mark_frame_reg = 1'b0; -reg send_frame_reg = 1'b0; -reg overflow_reg = 1'b0; -reg bad_frame_reg = 1'b0; -reg good_frame_reg = 1'b0; - -reg m_drop_frame_reg = 1'b0; -reg m_terminate_frame_reg = 1'b0; - -reg [ADDR_WIDTH:0] s_depth_reg = 0; -reg [ADDR_WIDTH:0] s_depth_commit_reg = 0; -reg [ADDR_WIDTH:0] m_depth_reg = 0; -reg [ADDR_WIDTH:0] m_depth_commit_reg = 0; - -reg overflow_sync1_reg = 1'b0; -reg overflow_sync2_reg = 1'b0; -reg overflow_sync3_reg = 1'b0; -reg overflow_sync4_reg = 1'b0; -reg bad_frame_sync1_reg = 1'b0; -reg bad_frame_sync2_reg = 1'b0; -reg bad_frame_sync3_reg = 1'b0; -reg bad_frame_sync4_reg = 1'b0; -reg good_frame_sync1_reg = 1'b0; -reg good_frame_sync2_reg = 1'b0; -reg good_frame_sync3_reg = 1'b0; -reg good_frame_sync4_reg = 1'b0; - -assign s_axis_tready = (FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : (!full || MARK_WHEN_FULL)) && !s_rst_sync3_reg; - -wire [WIDTH-1:0] s_axis; - -generate - assign s_axis[DATA_WIDTH-1:0] = s_axis_tdata; - if (KEEP_ENABLE) assign s_axis[KEEP_OFFSET +: KEEP_WIDTH] = s_axis_tkeep; - if (LAST_ENABLE) assign s_axis[LAST_OFFSET] = s_axis_tlast | mark_frame_reg; - if (ID_ENABLE) assign s_axis[ID_OFFSET +: ID_WIDTH] = s_axis_tid; - if (DEST_ENABLE) assign s_axis[DEST_OFFSET +: DEST_WIDTH] = s_axis_tdest; - if (USER_ENABLE) assign s_axis[USER_OFFSET +: USER_WIDTH] = mark_frame_reg ? USER_BAD_FRAME_VALUE : s_axis_tuser; -endgenerate - -wire [WIDTH-1:0] m_axis = m_axis_pipe_reg[RAM_PIPELINE+1-1]; - -wire m_axis_tready_pipe; -wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1]; - -wire [DATA_WIDTH-1:0] m_axis_tdata_pipe = m_axis[DATA_WIDTH-1:0]; -wire [KEEP_WIDTH-1:0] m_axis_tkeep_pipe = KEEP_ENABLE ? m_axis[KEEP_OFFSET +: KEEP_WIDTH] : {KEEP_WIDTH{1'b1}}; -wire m_axis_tlast_pipe = LAST_ENABLE ? m_axis[LAST_OFFSET] | m_terminate_frame_reg : 1'b1; -wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis[ID_OFFSET +: ID_WIDTH] : {ID_WIDTH{1'b0}}; -wire [DEST_WIDTH-1:0] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}}; -wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? (m_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis[USER_OFFSET +: USER_WIDTH]) : {USER_WIDTH{1'b0}}; - -wire m_axis_tready_out; -wire m_axis_tvalid_out; - -wire [DATA_WIDTH-1:0] m_axis_tdata_out; -wire [KEEP_WIDTH-1:0] m_axis_tkeep_out; -wire m_axis_tlast_out; -wire [ID_WIDTH-1:0] m_axis_tid_out; -wire [DEST_WIDTH-1:0] m_axis_tdest_out; -wire [USER_WIDTH-1:0] m_axis_tuser_out; - -wire pipe_ready; - -assign s_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_reg; -assign s_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_commit_reg; -assign s_status_overflow = overflow_reg; -assign s_status_bad_frame = bad_frame_reg; -assign s_status_good_frame = good_frame_reg; - -assign m_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_reg; -assign m_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_commit_reg; -assign m_status_overflow = overflow_sync3_reg ^ overflow_sync4_reg; -assign m_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg; -assign m_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg; - -// reset synchronization -always @(posedge m_clk or posedge m_rst) begin - if (m_rst) begin - s_rst_sync1_reg <= 1'b1; - end else begin - s_rst_sync1_reg <= 1'b0; - end -end - -always @(posedge s_clk) begin - s_rst_sync2_reg <= s_rst_sync1_reg; - s_rst_sync3_reg <= s_rst_sync2_reg; -end - -always @(posedge s_clk or posedge s_rst) begin - if (s_rst) begin - m_rst_sync1_reg <= 1'b1; - end else begin - m_rst_sync1_reg <= 1'b0; - end -end - -always @(posedge m_clk) begin - m_rst_sync2_reg <= m_rst_sync1_reg; - m_rst_sync3_reg <= m_rst_sync2_reg; -end - -// Write logic -always @(posedge s_clk) begin - overflow_reg <= 1'b0; - bad_frame_reg <= 1'b0; - good_frame_reg <= 1'b0; - - if (FRAME_FIFO && wr_ptr_update_valid_reg) begin - // have updated pointer to sync - if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin - // no sync in progress; sync update - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_sync_commit_reg <= wr_ptr_commit_reg; - wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; - end - end - - if (s_axis_tready && s_axis_tvalid && LAST_ENABLE) begin - // track input frame status - s_frame_reg <= !s_axis_tlast; - end - - if (s_rst_sync3_reg && LAST_ENABLE) begin - // if sink side is reset during transfer, drop partial frame - if (s_frame_reg && !(s_axis_tready && s_axis_tvalid && s_axis_tlast)) begin - drop_frame_reg <= 1'b1; - end - if (s_axis_tready && s_axis_tvalid && !s_axis_tlast) begin - drop_frame_reg <= 1'b1; - end - end - - if (FRAME_FIFO) begin - // frame FIFO mode - if (s_axis_tready && s_axis_tvalid) begin - // transfer in - if ((full && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin - // full, packet overflow, or currently dropping frame - // drop frame - drop_frame_reg <= 1'b1; - if (s_axis_tlast) begin - // end of frame, reset write pointer - wr_ptr_temp = wr_ptr_commit_reg; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - drop_frame_reg <= 1'b0; - overflow_reg <= 1'b1; - end - end else begin - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - if (s_axis_tlast || (!DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin - // end of frame or send frame - send_frame_reg <= !s_axis_tlast; - if (s_axis_tlast && DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~(s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin - // bad packet, reset write pointer - wr_ptr_temp = wr_ptr_commit_reg; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - bad_frame_reg <= 1'b1; - end else begin - // good packet or packet overflow, update write pointer - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - - if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin - // no sync in progress; sync update - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_sync_commit_reg <= wr_ptr_temp; - wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; - end else begin - // sync in progress; flag it for later - wr_ptr_update_valid_reg <= 1'b1; - end - - good_frame_reg <= s_axis_tlast; - end - end - end - end else if (s_axis_tvalid && full_wr && FRAME_FIFO && !DROP_OVERSIZE_FRAME) begin - // data valid with packet overflow - // update write pointer - send_frame_reg <= 1'b1; - wr_ptr_temp = wr_ptr_reg; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - - if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin - // no sync in progress; sync update - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_sync_commit_reg <= wr_ptr_temp; - wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg; - end else begin - // sync in progress; flag it for later - wr_ptr_update_valid_reg <= 1'b1; - end - end - end else begin - // normal FIFO mode - if (s_axis_tready && s_axis_tvalid) begin - if (drop_frame_reg && LAST_ENABLE) begin - // currently dropping frame - if (s_axis_tlast) begin - // end of frame - if (!full && mark_frame_reg && MARK_WHEN_FULL) begin - // terminate marked frame - mark_frame_reg <= 1'b0; - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - end - // end of frame, clear drop flag - drop_frame_reg <= 1'b0; - overflow_reg <= 1'b1; - end - end else if ((full || mark_frame_reg) && MARK_WHEN_FULL) begin - // full or marking frame - // drop frame; mark if this isn't the first cycle - drop_frame_reg <= 1'b1; - mark_frame_reg <= mark_frame_reg || s_frame_reg; - if (s_axis_tlast) begin - drop_frame_reg <= 1'b0; - overflow_reg <= 1'b1; - end - end else begin - // transfer in - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - end - end else if ((!full && !drop_frame_reg && mark_frame_reg) && MARK_WHEN_FULL) begin - // terminate marked frame - mark_frame_reg <= 1'b0; - mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; - wr_ptr_temp = wr_ptr_reg + 1; - wr_ptr_reg <= wr_ptr_temp; - wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); - end - end - - if (s_rst_sync3_reg) begin - wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_update_reg <= 1'b0; - end - - if (s_rst) begin - wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}}; - - wr_ptr_update_valid_reg <= 1'b0; - wr_ptr_update_reg <= 1'b0; - - s_frame_reg <= 1'b0; - - drop_frame_reg <= 1'b0; - mark_frame_reg <= 1'b0; - send_frame_reg <= 1'b0; - overflow_reg <= 1'b0; - bad_frame_reg <= 1'b0; - good_frame_reg <= 1'b0; - end -end - -// Write-side status -always @(posedge s_clk) begin - rd_ptr_conv_reg <= gray2bin(rd_ptr_gray_sync2_reg); - s_depth_reg <= wr_ptr_reg - rd_ptr_conv_reg; - s_depth_commit_reg <= wr_ptr_commit_reg - rd_ptr_conv_reg; -end - -// pointer synchronization -always @(posedge s_clk) begin - rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg; - rd_ptr_gray_sync2_reg <= rd_ptr_gray_sync1_reg; - wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg; - wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg; - - if (s_rst) begin - rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; - rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_update_ack_sync1_reg <= 1'b0; - wr_ptr_update_ack_sync2_reg <= 1'b0; - end -end - -always @(posedge m_clk) begin - wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg; - wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg; - if (FRAME_FIFO && wr_ptr_update_sync2_reg ^ wr_ptr_update_sync3_reg) begin - wr_ptr_commit_sync_reg <= wr_ptr_sync_commit_reg; - end - wr_ptr_update_sync1_reg <= wr_ptr_update_reg; - wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg; - wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg; - - if (FRAME_FIFO && m_rst_sync3_reg) begin - wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; - end - - if (m_rst) begin - wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_commit_sync_reg <= {ADDR_WIDTH+1{1'b0}}; - wr_ptr_update_sync1_reg <= 1'b0; - wr_ptr_update_sync2_reg <= 1'b0; - wr_ptr_update_sync3_reg <= 1'b0; - end -end - -// status synchronization -always @(posedge s_clk) begin - overflow_sync1_reg <= overflow_sync1_reg ^ overflow_reg; - bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg; - good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg; - - if (s_rst) begin - overflow_sync1_reg <= 1'b0; - bad_frame_sync1_reg <= 1'b0; - good_frame_sync1_reg <= 1'b0; - end -end - -always @(posedge m_clk) begin - overflow_sync2_reg <= overflow_sync1_reg; - overflow_sync3_reg <= overflow_sync2_reg; - overflow_sync4_reg <= overflow_sync3_reg; - bad_frame_sync2_reg <= bad_frame_sync1_reg; - bad_frame_sync3_reg <= bad_frame_sync2_reg; - bad_frame_sync4_reg <= bad_frame_sync3_reg; - good_frame_sync2_reg <= good_frame_sync1_reg; - good_frame_sync3_reg <= good_frame_sync2_reg; - good_frame_sync4_reg <= good_frame_sync3_reg; - - if (m_rst) begin - overflow_sync2_reg <= 1'b0; - overflow_sync3_reg <= 1'b0; - overflow_sync4_reg <= 1'b0; - bad_frame_sync2_reg <= 1'b0; - bad_frame_sync3_reg <= 1'b0; - bad_frame_sync4_reg <= 1'b0; - good_frame_sync2_reg <= 1'b0; - good_frame_sync3_reg <= 1'b0; - good_frame_sync4_reg <= 1'b0; - end -end - -// Read logic -integer j; - -always @(posedge m_clk) begin - if (m_axis_tready_pipe) begin - // output ready; invalidate stage - m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b0; - m_terminate_frame_reg <= 1'b0; - end - - for (j = RAM_PIPELINE+1-1; j > 0; j = j - 1) begin - if (m_axis_tready_pipe || ((~m_axis_tvalid_pipe_reg) >> j)) begin - // output ready or bubble in pipeline; transfer down pipeline - m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j-1]; - m_axis_pipe_reg[j] <= m_axis_pipe_reg[j-1]; - m_axis_tvalid_pipe_reg[j-1] <= 1'b0; - end - end - - if (m_axis_tready_pipe || ~m_axis_tvalid_pipe_reg) begin - // output ready or bubble in pipeline; read new data from FIFO - m_axis_tvalid_pipe_reg[0] <= 1'b0; - m_axis_pipe_reg[0] <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]]; - if (!empty && !m_rst_sync3_reg && !m_drop_frame_reg && pipe_ready) begin - // not empty, increment pointer - m_axis_tvalid_pipe_reg[0] <= 1'b1; - rd_ptr_temp = rd_ptr_reg + 1; - rd_ptr_reg <= rd_ptr_temp; - rd_ptr_gray_reg <= rd_ptr_temp ^ (rd_ptr_temp >> 1); - end - end - - if (m_axis_tvalid_pipe && LAST_ENABLE) begin - // track output frame status - if (m_axis_tlast_pipe && m_axis_tready_pipe) begin - m_frame_reg <= 1'b0; - end else begin - m_frame_reg <= 1'b1; - end - end - - if (m_drop_frame_reg && (OUTPUT_FIFO_ENABLE ? pipe_ready : m_axis_tready_pipe || !m_axis_tvalid_pipe) && LAST_ENABLE) begin - // terminate frame - // (only for frame transfers interrupted by source reset) - m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b1; - m_terminate_frame_reg <= 1'b1; - m_drop_frame_reg <= 1'b0; - end - - if (m_rst_sync3_reg && LAST_ENABLE) begin - // if source side is reset during transfer, drop partial frame - - // empty output pipeline, except for last stage - if (RAM_PIPELINE > 0) begin - m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-2:0] <= 0; - end - - if (m_frame_reg && (!m_axis_tvalid_pipe || (m_axis_tvalid_pipe && !m_axis_tlast_pipe)) && - !(m_drop_frame_reg || m_terminate_frame_reg)) begin - // terminate frame - m_drop_frame_reg <= 1'b1; - end - end - - if (m_rst_sync3_reg) begin - rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - end - - if (m_rst) begin - rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}}; - rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}}; - m_axis_tvalid_pipe_reg <= 0; - m_frame_reg <= 1'b0; - m_drop_frame_reg <= 1'b0; - m_terminate_frame_reg <= 1'b0; - end -end - -// Read-side status -always @(posedge m_clk) begin - wr_ptr_conv_reg <= gray2bin(wr_ptr_gray_sync2_reg); - m_depth_reg <= wr_ptr_conv_reg - rd_ptr_reg; - m_depth_commit_reg <= FRAME_FIFO ? wr_ptr_commit_sync_reg - rd_ptr_reg : wr_ptr_conv_reg - rd_ptr_reg; -end - -generate - -if (!OUTPUT_FIFO_ENABLE) begin - - assign pipe_ready = 1'b1; - - assign m_axis_tready_pipe = m_axis_tready_out; - assign m_axis_tvalid_out = m_axis_tvalid_pipe; - - assign m_axis_tdata_out = m_axis_tdata_pipe; - assign m_axis_tkeep_out = m_axis_tkeep_pipe; - assign m_axis_tlast_out = m_axis_tlast_pipe; - assign m_axis_tid_out = m_axis_tid_pipe; - assign m_axis_tdest_out = m_axis_tdest_pipe; - assign m_axis_tuser_out = m_axis_tuser_pipe; - -end else begin : output_fifo - - // output datapath logic - reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; - reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; - reg m_axis_tvalid_reg = 1'b0; - reg m_axis_tlast_reg = 1'b0; - reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; - reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; - reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - - reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0; - reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0; - reg out_fifo_half_full_reg = 1'b0; - - wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}}); - wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg; - - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [DATA_WIDTH-1:0] out_fifo_tdata[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg out_fifo_tlast[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [ID_WIDTH-1:0] out_fifo_tid[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [DEST_WIDTH-1:0] out_fifo_tdest[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - (* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *) - reg [USER_WIDTH-1:0] out_fifo_tuser[2**OUTPUT_FIFO_ADDR_WIDTH-1:0]; - - assign pipe_ready = !out_fifo_half_full_reg; - - assign m_axis_tready_pipe = 1'b1; - - assign m_axis_tdata_out = m_axis_tdata_reg; - assign m_axis_tkeep_out = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; - assign m_axis_tvalid_out = m_axis_tvalid_reg; - assign m_axis_tlast_out = LAST_ENABLE ? m_axis_tlast_reg : 1'b1; - assign m_axis_tid_out = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; - assign m_axis_tdest_out = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; - assign m_axis_tuser_out = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - - always @(posedge m_clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready_out; - - out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1); - - if (!out_fifo_full && m_axis_tvalid_pipe) begin - out_fifo_tdata[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_pipe; - out_fifo_tkeep[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_pipe; - out_fifo_tlast[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_pipe; - out_fifo_tid[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_pipe; - out_fifo_tdest[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_pipe; - out_fifo_tuser[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_pipe; - out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1; - end - - if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready_out)) begin - m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tvalid_reg <= 1'b1; - m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]]; - out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1; - end - - if (m_rst) begin - out_fifo_wr_ptr_reg <= 0; - out_fifo_rd_ptr_reg <= 0; - m_axis_tvalid_reg <= 1'b0; - end - end - -end - -if (PAUSE_ENABLE) begin : pause - - // Pause logic - reg pause_reg = 1'b0; - reg pause_frame_reg = 1'b0; - - reg s_pause_req_sync1_reg; - reg s_pause_req_sync2_reg; - reg s_pause_req_sync3_reg; - reg s_pause_ack_sync1_reg; - reg s_pause_ack_sync2_reg; - reg s_pause_ack_sync3_reg; - - always @(posedge s_clk) begin - s_pause_req_sync1_reg <= s_pause_req; - s_pause_ack_sync2_reg <= s_pause_ack_sync1_reg; - s_pause_ack_sync3_reg <= s_pause_ack_sync2_reg; - end - - always @(posedge m_clk) begin - s_pause_req_sync2_reg <= s_pause_req_sync1_reg; - s_pause_req_sync3_reg <= s_pause_req_sync2_reg; - s_pause_ack_sync1_reg <= pause_reg; - end - - assign m_axis_tready_out = m_axis_tready && !pause_reg; - assign m_axis_tvalid = m_axis_tvalid_out && !pause_reg; - - assign m_axis_tdata = m_axis_tdata_out; - assign m_axis_tkeep = m_axis_tkeep_out; - assign m_axis_tlast = m_axis_tlast_out; - assign m_axis_tid = m_axis_tid_out; - assign m_axis_tdest = m_axis_tdest_out; - assign m_axis_tuser = m_axis_tuser_out; - - assign s_pause_ack = s_pause_ack_sync3_reg; - assign m_pause_ack = pause_reg; - - always @(posedge m_clk) begin - if (FRAME_PAUSE) begin - if (pause_reg) begin - // paused; update pause status - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end else if (m_axis_tvalid_out) begin - // frame transfer; set frame bit - pause_frame_reg <= 1'b1; - if (m_axis_tready && m_axis_tlast) begin - // end of frame; clear frame bit and update pause status - pause_frame_reg <= 1'b0; - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end - end else if (!pause_frame_reg) begin - // idle; update pause status - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end - end else begin - pause_reg <= m_pause_req || s_pause_req_sync3_reg; - end - - if (m_rst) begin - pause_frame_reg <= 1'b0; - pause_reg <= 1'b0; - end - end - -end else begin - - assign m_axis_tready_out = m_axis_tready; - assign m_axis_tvalid = m_axis_tvalid_out; - - assign m_axis_tdata = m_axis_tdata_out; - assign m_axis_tkeep = m_axis_tkeep_out; - assign m_axis_tlast = m_axis_tlast_out; - assign m_axis_tid = m_axis_tid_out; - assign m_axis_tdest = m_axis_tdest_out; - assign m_axis_tuser = m_axis_tuser_out; - - assign s_pause_ack = 1'b0; - assign m_pause_ack = 1'b0; - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/axis_async_fifo_adapter.sv b/src/rvvi/axis_async_fifo_adapter.sv deleted file mode 100644 index d1e71b9fc..000000000 --- a/src/rvvi/axis_async_fifo_adapter.sv +++ /dev/null @@ -1,377 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream asynchronous FIFO with width converter - */ -module axis_async_fifo_adapter # -( - // FIFO depth in words - // KEEP_WIDTH words per cycle if KEEP_ENABLE set - // Rounded up to nearest power of 2 cycles - parameter DEPTH = 4096, - // Width of input AXI stream interface in bits - parameter S_DATA_WIDTH = 8, - // Propagate tkeep signal on input interface - // If disabled, tkeep assumed to be 1'b1 - parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on input interface - parameter S_KEEP_WIDTH = ((S_DATA_WIDTH+7)/8), - // Width of output AXI stream interface in bits - parameter M_DATA_WIDTH = 8, - // Propagate tkeep signal on output interface - // If disabled, tkeep assumed to be 1'b1 - parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8), - // tkeep signal width (words per cycle) on output interface - parameter M_KEEP_WIDTH = ((M_DATA_WIDTH+7)/8), - // Propagate tid signal - parameter ID_ENABLE = 0, - // tid signal width - parameter ID_WIDTH = 8, - // Propagate tdest signal - parameter DEST_ENABLE = 0, - // tdest signal width - parameter DEST_WIDTH = 8, - // Propagate tuser signal - parameter USER_ENABLE = 1, - // tuser signal width - parameter USER_WIDTH = 1, - // number of RAM pipeline registers in FIFO - parameter RAM_PIPELINE = 1, - // use output FIFO - // When set, the RAM read enable and pipeline clock enables are removed - parameter OUTPUT_FIFO_ENABLE = 0, - // Frame FIFO mode - operate on frames instead of cycles - // When set, m_axis_tvalid will not be deasserted within a frame - // Requires LAST_ENABLE set - parameter FRAME_FIFO = 0, - // tuser value for bad frame marker - parameter USER_BAD_FRAME_VALUE = 1'b1, - // tuser mask for bad frame marker - parameter USER_BAD_FRAME_MASK = 1'b1, - // Drop frames larger than FIFO - // Requires FRAME_FIFO set - parameter DROP_OVERSIZE_FRAME = FRAME_FIFO, - // Drop frames marked bad - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_BAD_FRAME = 0, - // Drop incoming frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO and DROP_OVERSIZE_FRAME set - parameter DROP_WHEN_FULL = 0, - // Mark incoming frames as bad frames when full - // When set, s_axis_tready is always asserted - // Requires FRAME_FIFO to be clear - parameter MARK_WHEN_FULL = 0, - // Enable pause request input - parameter PAUSE_ENABLE = 0, - // Pause between frames - parameter FRAME_PAUSE = FRAME_FIFO -) -( - /* - * AXI input - */ - input wire s_clk, - input wire s_rst, - input wire [S_DATA_WIDTH-1:0] s_axis_tdata, - input wire [S_KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI output - */ - input wire m_clk, - input wire m_rst, - output wire [M_DATA_WIDTH-1:0] m_axis_tdata, - output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * Pause - */ - input wire s_pause_req, - output wire s_pause_ack, - input wire m_pause_req, - output wire m_pause_ack, - - /* - * Status - */ - output wire [$clog2(DEPTH):0] s_status_depth, - output wire [$clog2(DEPTH):0] s_status_depth_commit, - output wire s_status_overflow, - output wire s_status_bad_frame, - output wire s_status_good_frame, - output wire [$clog2(DEPTH):0] m_status_depth, - output wire [$clog2(DEPTH):0] m_status_depth_commit, - output wire m_status_overflow, - output wire m_status_bad_frame, - output wire m_status_good_frame -); - -// force keep width to 1 when disabled -localparam S_BYTE_LANES = S_KEEP_ENABLE ? S_KEEP_WIDTH : 1; -localparam M_BYTE_LANES = M_KEEP_ENABLE ? M_KEEP_WIDTH : 1; - -// bus byte sizes (must be identical) -localparam S_BYTE_SIZE = S_DATA_WIDTH / S_BYTE_LANES; -localparam M_BYTE_SIZE = M_DATA_WIDTH / M_BYTE_LANES; -// output bus is wider -localparam EXPAND_BUS = M_BYTE_LANES > S_BYTE_LANES; -// total data and keep widths -localparam DATA_WIDTH = EXPAND_BUS ? M_DATA_WIDTH : S_DATA_WIDTH; -localparam KEEP_WIDTH = EXPAND_BUS ? M_BYTE_LANES : S_BYTE_LANES; - -// bus width assertions -initial begin - if (S_BYTE_SIZE * S_BYTE_LANES != S_DATA_WIDTH) begin - $error("Error: input data width not evenly divisible (instance %m)"); - $finish; - end - - if (M_BYTE_SIZE * M_BYTE_LANES != M_DATA_WIDTH) begin - $error("Error: output data width not evenly divisible (instance %m)"); - $finish; - end - - if (S_BYTE_SIZE != M_BYTE_SIZE) begin - $error("Error: byte size mismatch (instance %m)"); - $finish; - end -end - -wire [DATA_WIDTH-1:0] pre_fifo_axis_tdata; -wire [KEEP_WIDTH-1:0] pre_fifo_axis_tkeep; -wire pre_fifo_axis_tvalid; -wire pre_fifo_axis_tready; -wire pre_fifo_axis_tlast; -wire [ID_WIDTH-1:0] pre_fifo_axis_tid; -wire [DEST_WIDTH-1:0] pre_fifo_axis_tdest; -wire [USER_WIDTH-1:0] pre_fifo_axis_tuser; - -wire [DATA_WIDTH-1:0] post_fifo_axis_tdata; -wire [KEEP_WIDTH-1:0] post_fifo_axis_tkeep; -wire post_fifo_axis_tvalid; -wire post_fifo_axis_tready; -wire post_fifo_axis_tlast; -wire [ID_WIDTH-1:0] post_fifo_axis_tid; -wire [DEST_WIDTH-1:0] post_fifo_axis_tdest; -wire [USER_WIDTH-1:0] post_fifo_axis_tuser; - -generate - -if (M_BYTE_LANES > S_BYTE_LANES) begin : upsize_pre - - // output wider, adapt width before FIFO - - axis_adapter #( - .S_DATA_WIDTH(S_DATA_WIDTH), - .S_KEEP_ENABLE(S_KEEP_ENABLE), - .S_KEEP_WIDTH(S_KEEP_WIDTH), - .M_DATA_WIDTH(M_DATA_WIDTH), - .M_KEEP_ENABLE(M_KEEP_ENABLE), - .M_KEEP_WIDTH(M_KEEP_WIDTH), - .ID_ENABLE(ID_ENABLE), - .ID_WIDTH(ID_WIDTH), - .DEST_ENABLE(DEST_ENABLE), - .DEST_WIDTH(DEST_WIDTH), - .USER_ENABLE(USER_ENABLE), - .USER_WIDTH(USER_WIDTH) - ) - adapter_inst ( - .clk(s_clk), - .rst(s_rst), - // AXI input - .s_axis_tdata(s_axis_tdata), - .s_axis_tkeep(s_axis_tkeep), - .s_axis_tvalid(s_axis_tvalid), - .s_axis_tready(s_axis_tready), - .s_axis_tlast(s_axis_tlast), - .s_axis_tid(s_axis_tid), - .s_axis_tdest(s_axis_tdest), - .s_axis_tuser(s_axis_tuser), - // AXI output - .m_axis_tdata(pre_fifo_axis_tdata), - .m_axis_tkeep(pre_fifo_axis_tkeep), - .m_axis_tvalid(pre_fifo_axis_tvalid), - .m_axis_tready(pre_fifo_axis_tready), - .m_axis_tlast(pre_fifo_axis_tlast), - .m_axis_tid(pre_fifo_axis_tid), - .m_axis_tdest(pre_fifo_axis_tdest), - .m_axis_tuser(pre_fifo_axis_tuser) - ); - -end else begin : bypass_pre - - assign pre_fifo_axis_tdata = s_axis_tdata; - assign pre_fifo_axis_tkeep = s_axis_tkeep; - assign pre_fifo_axis_tvalid = s_axis_tvalid; - assign s_axis_tready = pre_fifo_axis_tready; - assign pre_fifo_axis_tlast = s_axis_tlast; - assign pre_fifo_axis_tid = s_axis_tid; - assign pre_fifo_axis_tdest = s_axis_tdest; - assign pre_fifo_axis_tuser = s_axis_tuser; - -end - -axis_async_fifo #( - .DEPTH(DEPTH), - .DATA_WIDTH(DATA_WIDTH), - .KEEP_ENABLE(EXPAND_BUS ? M_KEEP_ENABLE : S_KEEP_ENABLE), - .KEEP_WIDTH(KEEP_WIDTH), - .LAST_ENABLE(1), - .ID_ENABLE(ID_ENABLE), - .ID_WIDTH(ID_WIDTH), - .DEST_ENABLE(DEST_ENABLE), - .DEST_WIDTH(DEST_WIDTH), - .USER_ENABLE(USER_ENABLE), - .USER_WIDTH(USER_WIDTH), - .RAM_PIPELINE(RAM_PIPELINE), - .OUTPUT_FIFO_ENABLE(OUTPUT_FIFO_ENABLE), - .FRAME_FIFO(FRAME_FIFO), - .USER_BAD_FRAME_VALUE(USER_BAD_FRAME_VALUE), - .USER_BAD_FRAME_MASK(USER_BAD_FRAME_MASK), - .DROP_OVERSIZE_FRAME(DROP_OVERSIZE_FRAME), - .DROP_BAD_FRAME(DROP_BAD_FRAME), - .DROP_WHEN_FULL(DROP_WHEN_FULL), - .MARK_WHEN_FULL(MARK_WHEN_FULL), - .PAUSE_ENABLE(PAUSE_ENABLE), - .FRAME_PAUSE(FRAME_PAUSE) -) -fifo_inst ( - // AXI input - .s_clk(s_clk), - .s_rst(s_rst), - .s_axis_tdata(pre_fifo_axis_tdata), - .s_axis_tkeep(pre_fifo_axis_tkeep), - .s_axis_tvalid(pre_fifo_axis_tvalid), - .s_axis_tready(pre_fifo_axis_tready), - .s_axis_tlast(pre_fifo_axis_tlast), - .s_axis_tid(pre_fifo_axis_tid), - .s_axis_tdest(pre_fifo_axis_tdest), - .s_axis_tuser(pre_fifo_axis_tuser), - // AXI output - .m_clk(m_clk), - .m_rst(m_rst), - .m_axis_tdata(post_fifo_axis_tdata), - .m_axis_tkeep(post_fifo_axis_tkeep), - .m_axis_tvalid(post_fifo_axis_tvalid), - .m_axis_tready(post_fifo_axis_tready), - .m_axis_tlast(post_fifo_axis_tlast), - .m_axis_tid(post_fifo_axis_tid), - .m_axis_tdest(post_fifo_axis_tdest), - .m_axis_tuser(post_fifo_axis_tuser), - // Pause - .s_pause_req(s_pause_req), - .s_pause_ack(s_pause_ack), - .m_pause_req(m_pause_req), - .m_pause_ack(m_pause_ack), - // Status - .s_status_depth(s_status_depth), - .s_status_depth_commit(s_status_depth_commit), - .s_status_overflow(s_status_overflow), - .s_status_bad_frame(s_status_bad_frame), - .s_status_good_frame(s_status_good_frame), - .m_status_depth(m_status_depth), - .m_status_depth_commit(m_status_depth_commit), - .m_status_overflow(m_status_overflow), - .m_status_bad_frame(m_status_bad_frame), - .m_status_good_frame(m_status_good_frame) -); - -if (M_BYTE_LANES < S_BYTE_LANES) begin : downsize_post - - // input wider, adapt width after FIFO - - axis_adapter #( - .S_DATA_WIDTH(S_DATA_WIDTH), - .S_KEEP_ENABLE(S_KEEP_ENABLE), - .S_KEEP_WIDTH(S_KEEP_WIDTH), - .M_DATA_WIDTH(M_DATA_WIDTH), - .M_KEEP_ENABLE(M_KEEP_ENABLE), - .M_KEEP_WIDTH(M_KEEP_WIDTH), - .ID_ENABLE(ID_ENABLE), - .ID_WIDTH(ID_WIDTH), - .DEST_ENABLE(DEST_ENABLE), - .DEST_WIDTH(DEST_WIDTH), - .USER_ENABLE(USER_ENABLE), - .USER_WIDTH(USER_WIDTH) - ) - adapter_inst ( - .clk(m_clk), - .rst(m_rst), - // AXI input - .s_axis_tdata(post_fifo_axis_tdata), - .s_axis_tkeep(post_fifo_axis_tkeep), - .s_axis_tvalid(post_fifo_axis_tvalid), - .s_axis_tready(post_fifo_axis_tready), - .s_axis_tlast(post_fifo_axis_tlast), - .s_axis_tid(post_fifo_axis_tid), - .s_axis_tdest(post_fifo_axis_tdest), - .s_axis_tuser(post_fifo_axis_tuser), - // AXI output - .m_axis_tdata(m_axis_tdata), - .m_axis_tkeep(m_axis_tkeep), - .m_axis_tvalid(m_axis_tvalid), - .m_axis_tready(m_axis_tready), - .m_axis_tlast(m_axis_tlast), - .m_axis_tid(m_axis_tid), - .m_axis_tdest(m_axis_tdest), - .m_axis_tuser(m_axis_tuser) - ); - -end else begin : bypass_post - - assign m_axis_tdata = post_fifo_axis_tdata; - assign m_axis_tkeep = post_fifo_axis_tkeep; - assign m_axis_tvalid = post_fifo_axis_tvalid; - assign post_fifo_axis_tready = m_axis_tready; - assign m_axis_tlast = post_fifo_axis_tlast; - assign m_axis_tid = post_fifo_axis_tid; - assign m_axis_tdest = post_fifo_axis_tdest; - assign m_axis_tuser = post_fifo_axis_tuser; - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/axis_gmii_rx.sv b/src/rvvi/axis_gmii_rx.sv deleted file mode 100644 index 037fce77a..000000000 --- a/src/rvvi/axis_gmii_rx.sv +++ /dev/null @@ -1,357 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream GMII frame receiver (GMII in, AXI out) - */ -module axis_gmii_rx # -( - parameter DATA_WIDTH = 8, - parameter PTP_TS_ENABLE = 0, - parameter PTP_TS_WIDTH = 96, - parameter USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1 -) -( - input wire clk, - input wire rst, - - /* - * GMII input - */ - input wire [DATA_WIDTH-1:0] gmii_rxd, - input wire gmii_rx_dv, - input wire gmii_rx_er, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire m_axis_tvalid, - output wire m_axis_tlast, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * PTP - */ - input wire [PTP_TS_WIDTH-1:0] ptp_ts, - - /* - * Control - */ - input wire clk_enable, - input wire mii_select, - - /* - * Configuration - */ - input wire cfg_rx_enable, - - /* - * Status - */ - output wire start_packet, - output wire error_bad_frame, - output wire error_bad_fcs -); - -// bus width assertions -initial begin - if (DATA_WIDTH != 8) begin - $error("Error: Interface width must be 8"); - $finish; - end -end - -localparam [7:0] - ETH_PRE = 8'h55, - ETH_SFD = 8'hD5; - -localparam [2:0] - STATE_IDLE = 3'd0, - STATE_PAYLOAD = 3'd1, - STATE_WAIT_LAST = 3'd2; - -reg [2:0] state_reg = STATE_IDLE, state_next; - -// datapath control signals -reg reset_crc; -reg update_crc; - -reg mii_odd = 1'b0; -reg in_frame = 1'b0; - -reg [DATA_WIDTH-1:0] gmii_rxd_d0 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d1 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d2 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d3 = {DATA_WIDTH{1'b0}}; -reg [DATA_WIDTH-1:0] gmii_rxd_d4 = {DATA_WIDTH{1'b0}}; - -reg gmii_rx_dv_d0 = 1'b0; -reg gmii_rx_dv_d1 = 1'b0; -reg gmii_rx_dv_d2 = 1'b0; -reg gmii_rx_dv_d3 = 1'b0; -reg gmii_rx_dv_d4 = 1'b0; - -reg gmii_rx_er_d0 = 1'b0; -reg gmii_rx_er_d1 = 1'b0; -reg gmii_rx_er_d2 = 1'b0; -reg gmii_rx_er_d3 = 1'b0; -reg gmii_rx_er_d4 = 1'b0; - -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}, m_axis_tdata_next; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0, m_axis_tlast_next; -reg m_axis_tuser_reg = 1'b0, m_axis_tuser_next; - -reg start_packet_int_reg = 1'b0; -reg start_packet_reg = 1'b0; -reg error_bad_frame_reg = 1'b0, error_bad_frame_next; -reg error_bad_fcs_reg = 1'b0, error_bad_fcs_next; - -reg [PTP_TS_WIDTH-1:0] ptp_ts_reg = 0; - -reg [31:0] crc_state = 32'hFFFFFFFF; -wire [31:0] crc_next; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tuser = PTP_TS_ENABLE ? {ptp_ts_reg, m_axis_tuser_reg} : m_axis_tuser_reg; - -assign start_packet = start_packet_reg; -assign error_bad_frame = error_bad_frame_reg; -assign error_bad_fcs = error_bad_fcs_reg; - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(8), - .STYLE("AUTO") -) -eth_crc_8 ( - .data_in(gmii_rxd_d4), - .state_in(crc_state), - .data_out(), - .state_out(crc_next) -); - -always @* begin - state_next = STATE_IDLE; - - reset_crc = 1'b0; - update_crc = 1'b0; - - m_axis_tdata_next = {DATA_WIDTH{1'b0}}; - m_axis_tvalid_next = 1'b0; - m_axis_tlast_next = 1'b0; - m_axis_tuser_next = 1'b0; - - error_bad_frame_next = 1'b0; - error_bad_fcs_next = 1'b0; - - if (!clk_enable) begin - // clock disabled - hold state - state_next = state_reg; - end else if (mii_select && !mii_odd) begin - // MII even cycle - hold state - state_next = state_reg; - end else begin - case (state_reg) - STATE_IDLE: begin - // idle state - wait for packet - reset_crc = 1'b1; - - if (gmii_rx_dv_d4 && !gmii_rx_er_d4 && gmii_rxd_d4 == ETH_SFD && cfg_rx_enable) begin - state_next = STATE_PAYLOAD; - end else begin - state_next = STATE_IDLE; - end - end - STATE_PAYLOAD: begin - // read payload - update_crc = 1'b1; - - m_axis_tdata_next = gmii_rxd_d4; - m_axis_tvalid_next = 1'b1; - - if (gmii_rx_dv_d4 && gmii_rx_er_d4) begin - // error - m_axis_tlast_next = 1'b1; - m_axis_tuser_next = 1'b1; - error_bad_frame_next = 1'b1; - state_next = STATE_WAIT_LAST; - end else if (!gmii_rx_dv) begin - // end of packet - m_axis_tlast_next = 1'b1; - if (gmii_rx_er_d0 || gmii_rx_er_d1 || gmii_rx_er_d2 || gmii_rx_er_d3) begin - // error received in FCS bytes - m_axis_tuser_next = 1'b1; - error_bad_frame_next = 1'b1; - end else if ({gmii_rxd_d0, gmii_rxd_d1, gmii_rxd_d2, gmii_rxd_d3} == ~crc_next) begin - // FCS good - m_axis_tuser_next = 1'b0; - end else begin - // FCS bad - m_axis_tuser_next = 1'b1; - error_bad_frame_next = 1'b1; - error_bad_fcs_next = 1'b1; - end - state_next = STATE_IDLE; - end else begin - state_next = STATE_PAYLOAD; - end - end - STATE_WAIT_LAST: begin - // wait for end of packet - - if (~gmii_rx_dv) begin - state_next = STATE_IDLE; - end else begin - state_next = STATE_WAIT_LAST; - end - end - endcase - end -end - -always @(posedge clk) begin - state_reg <= state_next; - - m_axis_tdata_reg <= m_axis_tdata_next; - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tlast_reg <= m_axis_tlast_next; - m_axis_tuser_reg <= m_axis_tuser_next; - - start_packet_int_reg <= 1'b0; - start_packet_reg <= 1'b0; - - if (start_packet_int_reg) begin - ptp_ts_reg <= ptp_ts; - start_packet_reg <= 1'b1; - end - - if (clk_enable) begin - if (mii_select) begin - mii_odd <= !mii_odd; - - if (in_frame) begin - in_frame <= gmii_rx_dv; - end else if (gmii_rx_dv && {gmii_rxd[3:0], gmii_rxd_d0[7:4]} == ETH_SFD) begin - in_frame <= 1'b1; - start_packet_int_reg <= 1'b1; - mii_odd <= 1'b1; - end - - gmii_rxd_d0 <= {gmii_rxd[3:0], gmii_rxd_d0[7:4]}; - - if (mii_odd) begin - gmii_rxd_d1 <= gmii_rxd_d0; - gmii_rxd_d2 <= gmii_rxd_d1; - gmii_rxd_d3 <= gmii_rxd_d2; - gmii_rxd_d4 <= gmii_rxd_d3; - - gmii_rx_dv_d0 <= gmii_rx_dv & gmii_rx_dv_d0; - gmii_rx_dv_d1 <= gmii_rx_dv_d0 & gmii_rx_dv; - gmii_rx_dv_d2 <= gmii_rx_dv_d1 & gmii_rx_dv; - gmii_rx_dv_d3 <= gmii_rx_dv_d2 & gmii_rx_dv; - gmii_rx_dv_d4 <= gmii_rx_dv_d3 & gmii_rx_dv; - - gmii_rx_er_d0 <= gmii_rx_er | gmii_rx_er_d0; - gmii_rx_er_d1 <= gmii_rx_er_d0; - gmii_rx_er_d2 <= gmii_rx_er_d1; - gmii_rx_er_d3 <= gmii_rx_er_d2; - gmii_rx_er_d4 <= gmii_rx_er_d3; - end else begin - gmii_rx_dv_d0 <= gmii_rx_dv; - gmii_rx_er_d0 <= gmii_rx_er; - end - end else begin - if (in_frame) begin - in_frame <= gmii_rx_dv; - end else if (gmii_rx_dv && gmii_rxd == ETH_SFD) begin - in_frame <= 1'b1; - start_packet_int_reg <= 1'b1; - end - - gmii_rxd_d0 <= gmii_rxd; - gmii_rxd_d1 <= gmii_rxd_d0; - gmii_rxd_d2 <= gmii_rxd_d1; - gmii_rxd_d3 <= gmii_rxd_d2; - gmii_rxd_d4 <= gmii_rxd_d3; - - gmii_rx_dv_d0 <= gmii_rx_dv; - gmii_rx_dv_d1 <= gmii_rx_dv_d0 & gmii_rx_dv; - gmii_rx_dv_d2 <= gmii_rx_dv_d1 & gmii_rx_dv; - gmii_rx_dv_d3 <= gmii_rx_dv_d2 & gmii_rx_dv; - gmii_rx_dv_d4 <= gmii_rx_dv_d3 & gmii_rx_dv; - - gmii_rx_er_d0 <= gmii_rx_er; - gmii_rx_er_d1 <= gmii_rx_er_d0; - gmii_rx_er_d2 <= gmii_rx_er_d1; - gmii_rx_er_d3 <= gmii_rx_er_d2; - gmii_rx_er_d4 <= gmii_rx_er_d3; - end - end - - if (reset_crc) begin - crc_state <= 32'hFFFFFFFF; - end else if (update_crc) begin - crc_state <= crc_next; - end - - error_bad_frame_reg <= error_bad_frame_next; - error_bad_fcs_reg <= error_bad_fcs_next; - - if (rst) begin - state_reg <= STATE_IDLE; - - m_axis_tvalid_reg <= 1'b0; - - start_packet_int_reg <= 1'b0; - start_packet_reg <= 1'b0; - error_bad_frame_reg <= 1'b0; - error_bad_fcs_reg <= 1'b0; - - in_frame <= 1'b0; - mii_odd <= 1'b0; - - gmii_rx_dv_d0 <= 1'b0; - gmii_rx_dv_d1 <= 1'b0; - gmii_rx_dv_d2 <= 1'b0; - gmii_rx_dv_d3 <= 1'b0; - gmii_rx_dv_d4 <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/axis_gmii_tx.sv b/src/rvvi/axis_gmii_tx.sv deleted file mode 100644 index f2936039f..000000000 --- a/src/rvvi/axis_gmii_tx.sv +++ /dev/null @@ -1,457 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream GMII frame transmitter (AXI in, GMII out) - */ -module axis_gmii_tx # -( - parameter DATA_WIDTH = 8, - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64, - parameter PTP_TS_ENABLE = 0, - parameter PTP_TS_WIDTH = 96, - parameter PTP_TS_CTRL_IN_TUSER = 0, - parameter PTP_TAG_ENABLE = PTP_TS_ENABLE, - parameter PTP_TAG_WIDTH = 16, - parameter USER_WIDTH = (PTP_TS_ENABLE ? (PTP_TAG_ENABLE ? PTP_TAG_WIDTH : 0) + (PTP_TS_CTRL_IN_TUSER ? 1 : 0) : 0) + 1 -) -( - input wire clk, - input wire rst, - - /* - * AXI input - */ - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * GMII output - */ - output wire [DATA_WIDTH-1:0] gmii_txd, - output wire gmii_tx_en, - output wire gmii_tx_er, - - /* - * PTP - */ - input wire [PTP_TS_WIDTH-1:0] ptp_ts, - output wire [PTP_TS_WIDTH-1:0] m_axis_ptp_ts, - output wire [PTP_TAG_WIDTH-1:0] m_axis_ptp_ts_tag, - output wire m_axis_ptp_ts_valid, - - /* - * Control - */ - input wire clk_enable, - input wire mii_select, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - - /* - * Status - */ - output wire start_packet, - output wire error_underflow -); - -parameter MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-1+1); - -// bus width assertions -initial begin - if (DATA_WIDTH != 8) begin - $error("Error: Interface width must be 8"); - $finish; - end -end - -localparam [7:0] - ETH_PRE = 8'h55, - ETH_SFD = 8'hD5; - -localparam [2:0] - STATE_IDLE = 3'd0, - STATE_PREAMBLE = 3'd1, - STATE_PAYLOAD = 3'd2, - STATE_LAST = 3'd3, - STATE_PAD = 3'd4, - STATE_FCS = 3'd5, - STATE_IFG = 3'd6; - -reg [2:0] state_reg = STATE_IDLE, state_next; - -// datapath control signals -reg reset_crc; -reg update_crc; - -reg [7:0] s_tdata_reg = 8'd0, s_tdata_next; - -reg mii_odd_reg = 1'b0, mii_odd_next; -reg [3:0] mii_msn_reg = 4'b0, mii_msn_next; - -reg frame_reg = 1'b0, frame_next; -reg frame_error_reg = 1'b0, frame_error_next; -reg [7:0] frame_ptr_reg = 0, frame_ptr_next; -reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; - -reg [7:0] gmii_txd_reg = 8'd0, gmii_txd_next; -reg gmii_tx_en_reg = 1'b0, gmii_tx_en_next; -reg gmii_tx_er_reg = 1'b0, gmii_tx_er_next; - -reg s_axis_tready_reg = 1'b0, s_axis_tready_next; - -reg [PTP_TS_WIDTH-1:0] m_axis_ptp_ts_reg = 0, m_axis_ptp_ts_next; -reg [PTP_TAG_WIDTH-1:0] m_axis_ptp_ts_tag_reg = 0, m_axis_ptp_ts_tag_next; -reg m_axis_ptp_ts_valid_reg = 1'b0, m_axis_ptp_ts_valid_next; - -reg start_packet_int_reg = 1'b0, start_packet_int_next; -reg start_packet_reg = 1'b0, start_packet_next; -reg error_underflow_reg = 1'b0, error_underflow_next; - -reg [31:0] crc_state = 32'hFFFFFFFF; -wire [31:0] crc_next; - -assign s_axis_tready = s_axis_tready_reg; - -assign gmii_txd = gmii_txd_reg; -assign gmii_tx_en = gmii_tx_en_reg; -assign gmii_tx_er = gmii_tx_er_reg; - -assign m_axis_ptp_ts = PTP_TS_ENABLE ? m_axis_ptp_ts_reg : 0; -assign m_axis_ptp_ts_tag = PTP_TAG_ENABLE ? m_axis_ptp_ts_tag_reg : 0; -assign m_axis_ptp_ts_valid = PTP_TS_ENABLE || PTP_TAG_ENABLE ? m_axis_ptp_ts_valid_reg : 1'b0; - -assign start_packet = start_packet_reg; -assign error_underflow = error_underflow_reg; - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(8), - .STYLE("AUTO") -) -eth_crc_8 ( - .data_in(s_tdata_reg), - .state_in(crc_state), - .data_out(), - .state_out(crc_next) -); - -always @* begin - state_next = STATE_IDLE; - - reset_crc = 1'b0; - update_crc = 1'b0; - - mii_odd_next = mii_odd_reg; - mii_msn_next = mii_msn_reg; - - frame_next = frame_reg; - frame_error_next = frame_error_reg; - frame_ptr_next = frame_ptr_reg; - frame_min_count_next = frame_min_count_reg; - - s_axis_tready_next = 1'b0; - - s_tdata_next = s_tdata_reg; - - m_axis_ptp_ts_next = m_axis_ptp_ts_reg; - m_axis_ptp_ts_tag_next = m_axis_ptp_ts_tag_reg; - m_axis_ptp_ts_valid_next = 1'b0; - - if (start_packet_reg && PTP_TS_ENABLE) begin - m_axis_ptp_ts_next = ptp_ts; - if (PTP_TS_CTRL_IN_TUSER) begin - m_axis_ptp_ts_tag_next = s_axis_tuser >> 2; - m_axis_ptp_ts_valid_next = s_axis_tuser[1]; - end else begin - m_axis_ptp_ts_tag_next = s_axis_tuser >> 1; - m_axis_ptp_ts_valid_next = 1'b1; - end - end - - gmii_txd_next = {DATA_WIDTH{1'b0}}; - gmii_tx_en_next = 1'b0; - gmii_tx_er_next = 1'b0; - - start_packet_int_next = start_packet_int_reg; - start_packet_next = 1'b0; - error_underflow_next = 1'b0; - - if (s_axis_tvalid && s_axis_tready) begin - frame_next = !s_axis_tlast; - end - - if (!clk_enable) begin - // clock disabled - hold state and outputs - gmii_txd_next = gmii_txd_reg; - gmii_tx_en_next = gmii_tx_en_reg; - gmii_tx_er_next = gmii_tx_er_reg; - state_next = state_reg; - end else if (mii_select && mii_odd_reg) begin - // MII odd cycle - hold state, output MSN - mii_odd_next = 1'b0; - gmii_txd_next = {4'd0, mii_msn_reg}; - gmii_tx_en_next = gmii_tx_en_reg; - gmii_tx_er_next = gmii_tx_er_reg; - state_next = state_reg; - if (start_packet_int_reg) begin - start_packet_int_next = 1'b0; - start_packet_next = 1'b1; - end - end else begin - case (state_reg) - STATE_IDLE: begin - // idle state - wait for packet - reset_crc = 1'b1; - - mii_odd_next = 1'b0; - frame_ptr_next = 1; - - frame_error_next = 1'b0; - frame_min_count_next = MIN_FRAME_LENGTH-4-1; - - if (s_axis_tvalid && cfg_tx_enable) begin - mii_odd_next = 1'b1; - gmii_txd_next = ETH_PRE; - gmii_tx_en_next = 1'b1; - state_next = STATE_PREAMBLE; - end else begin - state_next = STATE_IDLE; - end - end - STATE_PREAMBLE: begin - // send preamble - reset_crc = 1'b1; - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - - gmii_txd_next = ETH_PRE; - gmii_tx_en_next = 1'b1; - - if (frame_ptr_reg == 6) begin - s_axis_tready_next = 1'b1; - s_tdata_next = s_axis_tdata; - state_next = STATE_PREAMBLE; - end else if (frame_ptr_reg == 7) begin - // end of preamble; start payload - frame_ptr_next = 0; - if (s_axis_tready_reg) begin - s_axis_tready_next = 1'b1; - s_tdata_next = s_axis_tdata; - end - gmii_txd_next = ETH_SFD; - if (mii_select) begin - start_packet_int_next = 1'b1; - end else begin - start_packet_next = 1'b1; - end - state_next = STATE_PAYLOAD; - end else begin - state_next = STATE_PREAMBLE; - end - end - STATE_PAYLOAD: begin - // send payload - - update_crc = 1'b1; - s_axis_tready_next = 1'b1; - - mii_odd_next = 1'b1; - - if (frame_min_count_reg) begin - frame_min_count_next = frame_min_count_reg - 1; - end - - gmii_txd_next = s_tdata_reg; - gmii_tx_en_next = 1'b1; - - s_tdata_next = s_axis_tdata; - - if (!s_axis_tvalid || s_axis_tlast) begin - s_axis_tready_next = frame_next; // drop frame - frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; - error_underflow_next = !s_axis_tvalid; - - state_next = STATE_LAST; - end else begin - state_next = STATE_PAYLOAD; - end - end - STATE_LAST: begin - // last payload word - - update_crc = 1'b1; - s_axis_tready_next = 1'b0; - - mii_odd_next = 1'b1; - - gmii_txd_next = s_tdata_reg; - gmii_tx_en_next = 1'b1; - - if (ENABLE_PADDING && frame_min_count_reg) begin - frame_min_count_next = frame_min_count_reg - 1; - s_tdata_next = 8'd0; - state_next = STATE_PAD; - end else begin - frame_ptr_next = 0; - state_next = STATE_FCS; - end - end - STATE_PAD: begin - // send padding - s_axis_tready_next = frame_next; // drop frame - - update_crc = 1'b1; - mii_odd_next = 1'b1; - - gmii_txd_next = 8'd0; - gmii_tx_en_next = 1'b1; - - s_tdata_next = 8'd0; - - if (frame_min_count_reg) begin - frame_min_count_next = frame_min_count_reg - 1; - state_next = STATE_PAD; - end else begin - frame_ptr_next = 0; - state_next = STATE_FCS; - end - end - STATE_FCS: begin - // send FCS - s_axis_tready_next = frame_next; // drop frame - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - - case (frame_ptr_reg) - 2'd0: gmii_txd_next = ~crc_state[7:0]; - 2'd1: gmii_txd_next = ~crc_state[15:8]; - 2'd2: gmii_txd_next = ~crc_state[23:16]; - 2'd3: gmii_txd_next = ~crc_state[31:24]; - endcase - gmii_tx_en_next = 1'b1; - gmii_tx_er_next = frame_error_reg; - - if (frame_ptr_reg < 3) begin - state_next = STATE_FCS; - end else begin - frame_ptr_next = 0; - state_next = STATE_IFG; - end - end - STATE_IFG: begin - // send IFG - s_axis_tready_next = frame_next; // drop frame - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - - if (frame_ptr_reg < cfg_ifg-1 || frame_reg) begin - state_next = STATE_IFG; - end else begin - state_next = STATE_IDLE; - end - end - endcase - - if (mii_select) begin - mii_msn_next = gmii_txd_next[7:4]; - gmii_txd_next[7:4] = 4'd0; - end - end -end - -always @(posedge clk) begin - state_reg <= state_next; - - frame_reg <= frame_next; - frame_error_reg <= frame_error_next; - frame_ptr_reg <= frame_ptr_next; - frame_min_count_reg <= frame_min_count_next; - - m_axis_ptp_ts_reg <= m_axis_ptp_ts_next; - m_axis_ptp_ts_tag_reg <= m_axis_ptp_ts_tag_next; - m_axis_ptp_ts_valid_reg <= m_axis_ptp_ts_valid_next; - - mii_odd_reg <= mii_odd_next; - mii_msn_reg <= mii_msn_next; - - s_tdata_reg <= s_tdata_next; - - s_axis_tready_reg <= s_axis_tready_next; - - gmii_txd_reg <= gmii_txd_next; - gmii_tx_en_reg <= gmii_tx_en_next; - gmii_tx_er_reg <= gmii_tx_er_next; - - if (reset_crc) begin - crc_state <= 32'hFFFFFFFF; - end else if (update_crc) begin - crc_state <= crc_next; - end - - start_packet_int_reg <= start_packet_int_next; - start_packet_reg <= start_packet_next; - error_underflow_reg <= error_underflow_next; - - if (rst) begin - state_reg <= STATE_IDLE; - - frame_reg <= 1'b0; - - s_axis_tready_reg <= 1'b0; - - m_axis_ptp_ts_valid_reg <= 1'b0; - - gmii_tx_en_reg <= 1'b0; - gmii_tx_er_reg <= 1'b0; - - start_packet_int_reg <= 1'b0; - start_packet_reg <= 1'b0; - error_underflow_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/eth_axis_tx.sv b/src/rvvi/eth_axis_tx.sv deleted file mode 100644 index b4287b281..000000000 --- a/src/rvvi/eth_axis_tx.sv +++ /dev/null @@ -1,408 +0,0 @@ -/* - -Copyright (c) 2014-2020 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * AXI4-Stream ethernet frame transmitter (Ethernet frame in, AXI out) - */ -module eth_axis_tx # -( - // Width of AXI stream interfaces in bits - parameter DATA_WIDTH = 8, - // Propagate tkeep signal - // If disabled, tkeep assumed to be 1'b1 - parameter KEEP_ENABLE = (DATA_WIDTH>8), - // tkeep signal width (words per cycle) - parameter KEEP_WIDTH = (DATA_WIDTH/8) -) -( - input wire clk, - input wire rst, - - /* - * Ethernet frame input - */ - input wire s_eth_hdr_valid, - output wire s_eth_hdr_ready, - input wire [47:0] s_eth_dest_mac, - input wire [47:0] s_eth_src_mac, - input wire [15:0] s_eth_type, - input wire [DATA_WIDTH-1:0] s_eth_payload_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_eth_payload_axis_tkeep, - input wire s_eth_payload_axis_tvalid, - output wire s_eth_payload_axis_tready, - input wire s_eth_payload_axis_tlast, - input wire s_eth_payload_axis_tuser, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire m_axis_tuser, - - /* - * Status signals - */ - output wire busy -); - -parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; - -parameter HDR_SIZE = 14; - -parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; - -parameter PTR_WIDTH = $clog2(CYCLE_COUNT); - -parameter OFFSET = HDR_SIZE % BYTE_LANES; - -// bus width assertions -initial begin - if (BYTE_LANES * 8 != DATA_WIDTH) begin - $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); - $finish; - end -end - -/* - -Ethernet frame - - Field Length - Destination MAC address 6 octets - Source MAC address 6 octets - Ethertype 2 octets - -This module receives an Ethernet frame with header fields in parallel along -with the payload in an AXI stream, combines the header with the payload, and -transmits the complete Ethernet frame on the output AXI stream interface. - -*/ - -// datapath control signals -reg store_eth_hdr; - -reg send_eth_header_reg = 1'b0, send_eth_header_next; -reg send_eth_payload_reg = 1'b0, send_eth_payload_next; -reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; - -reg flush_save; -reg transfer_in_save; - -reg [47:0] eth_dest_mac_reg = 48'd0; -reg [47:0] eth_src_mac_reg = 48'd0; -reg [15:0] eth_type_reg = 16'd0; - -reg s_eth_hdr_ready_reg = 1'b0, s_eth_hdr_ready_next; -reg s_eth_payload_axis_tready_reg = 1'b0, s_eth_payload_axis_tready_next; - -reg busy_reg = 1'b0; - -reg [DATA_WIDTH-1:0] save_eth_payload_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] save_eth_payload_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg save_eth_payload_axis_tlast_reg = 1'b0; -reg save_eth_payload_axis_tuser_reg = 1'b0; - -reg [DATA_WIDTH-1:0] shift_eth_payload_axis_tdata; -reg [KEEP_WIDTH-1:0] shift_eth_payload_axis_tkeep; -reg shift_eth_payload_axis_tvalid; -reg shift_eth_payload_axis_tlast; -reg shift_eth_payload_axis_tuser; -reg shift_eth_payload_axis_input_tready; -reg shift_eth_payload_axis_extra_cycle_reg = 1'b0; - -// internal datapath -reg [DATA_WIDTH-1:0] m_axis_tdata_int; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; -reg m_axis_tvalid_int; -reg m_axis_tready_int_reg = 1'b0; -reg m_axis_tlast_int; -reg m_axis_tuser_int; -wire m_axis_tready_int_early; - -assign s_eth_hdr_ready = s_eth_hdr_ready_reg; -assign s_eth_payload_axis_tready = s_eth_payload_axis_tready_reg; - -assign busy = busy_reg; - -always @* begin - if (OFFSET == 0) begin - // passthrough if no overlap - shift_eth_payload_axis_tdata = s_eth_payload_axis_tdata; - shift_eth_payload_axis_tkeep = s_eth_payload_axis_tkeep; - shift_eth_payload_axis_tvalid = s_eth_payload_axis_tvalid; - shift_eth_payload_axis_tlast = s_eth_payload_axis_tlast; - shift_eth_payload_axis_tuser = s_eth_payload_axis_tuser; - shift_eth_payload_axis_input_tready = 1'b1; - end else if (shift_eth_payload_axis_extra_cycle_reg) begin - shift_eth_payload_axis_tdata = {s_eth_payload_axis_tdata, save_eth_payload_axis_tdata_reg} >> ((KEEP_WIDTH-OFFSET)*8); - shift_eth_payload_axis_tkeep = {{KEEP_WIDTH{1'b0}}, save_eth_payload_axis_tkeep_reg} >> (KEEP_WIDTH-OFFSET); - shift_eth_payload_axis_tvalid = 1'b1; - shift_eth_payload_axis_tlast = save_eth_payload_axis_tlast_reg; - shift_eth_payload_axis_tuser = save_eth_payload_axis_tuser_reg; - shift_eth_payload_axis_input_tready = flush_save; - end else begin - shift_eth_payload_axis_tdata = {s_eth_payload_axis_tdata, save_eth_payload_axis_tdata_reg} >> ((KEEP_WIDTH-OFFSET)*8); - shift_eth_payload_axis_tkeep = {s_eth_payload_axis_tkeep, save_eth_payload_axis_tkeep_reg} >> (KEEP_WIDTH-OFFSET); - shift_eth_payload_axis_tvalid = s_eth_payload_axis_tvalid; - shift_eth_payload_axis_tlast = (s_eth_payload_axis_tlast && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) == 0)); - shift_eth_payload_axis_tuser = (s_eth_payload_axis_tuser && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) == 0)); - shift_eth_payload_axis_input_tready = !(s_eth_payload_axis_tlast && s_eth_payload_axis_tready && s_eth_payload_axis_tvalid); - end -end - -always @* begin - send_eth_header_next = send_eth_header_reg; - send_eth_payload_next = send_eth_payload_reg; - ptr_next = ptr_reg; - - s_eth_hdr_ready_next = 1'b0; - s_eth_payload_axis_tready_next = 1'b0; - - store_eth_hdr = 1'b0; - - flush_save = 1'b0; - transfer_in_save = 1'b0; - - m_axis_tdata_int = {DATA_WIDTH{1'b0}}; - m_axis_tkeep_int = {KEEP_WIDTH{1'b0}}; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = 1'b0; - m_axis_tuser_int = 1'b0; - - if (s_eth_hdr_ready && s_eth_hdr_valid) begin - store_eth_hdr = 1'b1; - ptr_next = 0; - send_eth_header_next = 1'b1; - send_eth_payload_next = (OFFSET != 0) && (CYCLE_COUNT == 1); - s_eth_payload_axis_tready_next = send_eth_payload_next && m_axis_tready_int_early; - end - - if (send_eth_payload_reg) begin - s_eth_payload_axis_tready_next = m_axis_tready_int_early && shift_eth_payload_axis_input_tready; - - m_axis_tdata_int = shift_eth_payload_axis_tdata; - m_axis_tkeep_int = shift_eth_payload_axis_tkeep; - m_axis_tlast_int = shift_eth_payload_axis_tlast; - m_axis_tuser_int = shift_eth_payload_axis_tuser; - - if ((s_eth_payload_axis_tready && s_eth_payload_axis_tvalid) || (m_axis_tready_int_reg && shift_eth_payload_axis_extra_cycle_reg)) begin - transfer_in_save = 1'b1; - - m_axis_tvalid_int = 1'b1; - - if (shift_eth_payload_axis_tlast) begin - flush_save = 1'b1; - s_eth_payload_axis_tready_next = 1'b0; - ptr_next = 0; - send_eth_payload_next = 1'b0; - end - end - end - - if (m_axis_tready_int_reg && (!OFFSET || !send_eth_payload_reg || m_axis_tvalid_int)) begin - if (send_eth_header_reg) begin - ptr_next = ptr_reg + 1; - - if ((OFFSET != 0) && (CYCLE_COUNT == 1 || ptr_next == CYCLE_COUNT-1) && !send_eth_payload_reg) begin - send_eth_payload_next = 1'b1; - s_eth_payload_axis_tready_next = m_axis_tready_int_early && shift_eth_payload_axis_input_tready; - end - - m_axis_tvalid_int = 1'b1; - - `define _HEADER_FIELD_(offset, field) \ - if (ptr_reg == offset/BYTE_LANES) begin \ - m_axis_tdata_int[(offset%BYTE_LANES)*8 +: 8] = field; \ - m_axis_tkeep_int[offset%BYTE_LANES] = 1'b1; \ - end - - `_HEADER_FIELD_(0, eth_dest_mac_reg[5*8 +: 8]) - `_HEADER_FIELD_(1, eth_dest_mac_reg[4*8 +: 8]) - `_HEADER_FIELD_(2, eth_dest_mac_reg[3*8 +: 8]) - `_HEADER_FIELD_(3, eth_dest_mac_reg[2*8 +: 8]) - `_HEADER_FIELD_(4, eth_dest_mac_reg[1*8 +: 8]) - `_HEADER_FIELD_(5, eth_dest_mac_reg[0*8 +: 8]) - `_HEADER_FIELD_(6, eth_src_mac_reg[5*8 +: 8]) - `_HEADER_FIELD_(7, eth_src_mac_reg[4*8 +: 8]) - `_HEADER_FIELD_(8, eth_src_mac_reg[3*8 +: 8]) - `_HEADER_FIELD_(9, eth_src_mac_reg[2*8 +: 8]) - `_HEADER_FIELD_(10, eth_src_mac_reg[1*8 +: 8]) - `_HEADER_FIELD_(11, eth_src_mac_reg[0*8 +: 8]) - `_HEADER_FIELD_(12, eth_type_reg[1*8 +: 8]) - `_HEADER_FIELD_(13, eth_type_reg[0*8 +: 8]) - - if (ptr_reg == 13/BYTE_LANES) begin - if (!send_eth_payload_reg) begin - s_eth_payload_axis_tready_next = m_axis_tready_int_early; - send_eth_payload_next = 1'b1; - end - send_eth_header_next = 1'b0; - end - - `undef _HEADER_FIELD_ - end - end - - s_eth_hdr_ready_next = !(send_eth_header_next || send_eth_payload_next); -end - -always @(posedge clk) begin - send_eth_header_reg <= send_eth_header_next; - send_eth_payload_reg <= send_eth_payload_next; - ptr_reg <= ptr_next; - - s_eth_hdr_ready_reg <= s_eth_hdr_ready_next; - s_eth_payload_axis_tready_reg <= s_eth_payload_axis_tready_next; - - busy_reg <= send_eth_header_next || send_eth_payload_next; - - if (store_eth_hdr) begin - eth_dest_mac_reg <= s_eth_dest_mac; - eth_src_mac_reg <= s_eth_src_mac; - eth_type_reg <= s_eth_type; - end - - if (transfer_in_save) begin - save_eth_payload_axis_tdata_reg <= s_eth_payload_axis_tdata; - save_eth_payload_axis_tkeep_reg <= s_eth_payload_axis_tkeep; - save_eth_payload_axis_tuser_reg <= s_eth_payload_axis_tuser; - end - - if (flush_save) begin - save_eth_payload_axis_tlast_reg <= 1'b0; - shift_eth_payload_axis_extra_cycle_reg <= 1'b0; - end else if (transfer_in_save) begin - save_eth_payload_axis_tlast_reg <= s_eth_payload_axis_tlast; - shift_eth_payload_axis_extra_cycle_reg <= OFFSET ? s_eth_payload_axis_tlast && ((s_eth_payload_axis_tkeep & ({KEEP_WIDTH{1'b1}} << (KEEP_WIDTH-OFFSET))) != 0) : 1'b0; - end - - if (rst) begin - send_eth_header_reg <= 1'b0; - send_eth_payload_reg <= 1'b0; - ptr_reg <= 0; - s_eth_hdr_ready_reg <= 1'b0; - s_eth_payload_axis_tready_reg <= 1'b0; - busy_reg <= 1'b0; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0; -reg m_axis_tuser_reg = 1'b0; - -reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; -reg temp_m_axis_tlast_reg = 1'b0; -reg temp_m_axis_tuser_reg = 1'b0; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tuser = m_axis_tuser_reg; - -// enable ready input next cycle if output is ready or if both output registers are empty -assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && !m_axis_tvalid_reg); - -always @* begin - // transfer sink ready state to source - m_axis_tvalid_next = m_axis_tvalid_reg; - temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (m_axis_tready_int_reg) begin - // input is ready - if (m_axis_tready || !m_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (m_axis_tready) begin - // input is not ready, but output is ready - m_axis_tvalid_next = temp_m_axis_tvalid_reg; - temp_m_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tready_int_reg <= m_axis_tready_int_early; - temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; - - // datapath - if (store_axis_int_to_output) begin - m_axis_tdata_reg <= m_axis_tdata_int; - m_axis_tkeep_reg <= m_axis_tkeep_int; - m_axis_tlast_reg <= m_axis_tlast_int; - m_axis_tuser_reg <= m_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - m_axis_tdata_reg <= temp_m_axis_tdata_reg; - m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; - m_axis_tlast_reg <= temp_m_axis_tlast_reg; - m_axis_tuser_reg <= temp_m_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_m_axis_tdata_reg <= m_axis_tdata_int; - temp_m_axis_tkeep_reg <= m_axis_tkeep_int; - temp_m_axis_tlast_reg <= m_axis_tlast_int; - temp_m_axis_tuser_reg <= m_axis_tuser_int; - end - - if (rst) begin - m_axis_tvalid_reg <= 1'b0; - m_axis_tready_int_reg <= 1'b0; - temp_m_axis_tvalid_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/eth_mac_1g.sv b/src/rvvi/eth_mac_1g.sv deleted file mode 100644 index 6e0592fac..000000000 --- a/src/rvvi/eth_mac_1g.sv +++ /dev/null @@ -1,643 +0,0 @@ -/* - -Copyright (c) 2015-2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * 1G Ethernet MAC - */ -module eth_mac_1g # -( - parameter DATA_WIDTH = 8, - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64, - parameter PTP_TS_ENABLE = 0, - parameter PTP_TS_FMT_TOD = 1, - parameter PTP_TS_WIDTH = PTP_TS_FMT_TOD ? 96 : 64, - parameter TX_PTP_TS_CTRL_IN_TUSER = 0, - parameter TX_PTP_TAG_ENABLE = PTP_TS_ENABLE, - parameter TX_PTP_TAG_WIDTH = 16, - parameter TX_USER_WIDTH = (PTP_TS_ENABLE ? (TX_PTP_TAG_ENABLE ? TX_PTP_TAG_WIDTH : 0) + (TX_PTP_TS_CTRL_IN_TUSER ? 1 : 0) : 0) + 1, - parameter RX_USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1, - parameter PFC_ENABLE = 0, - parameter PAUSE_ENABLE = PFC_ENABLE -) -( - input wire rx_clk, - input wire rx_rst, - input wire tx_clk, - input wire tx_rst, - - /* - * AXI input - */ - input wire [DATA_WIDTH-1:0] tx_axis_tdata, - input wire tx_axis_tvalid, - output wire tx_axis_tready, - input wire tx_axis_tlast, - input wire [TX_USER_WIDTH-1:0] tx_axis_tuser, - - /* - * AXI output - */ - output wire [DATA_WIDTH-1:0] rx_axis_tdata, - output wire rx_axis_tvalid, - output wire rx_axis_tlast, - output wire [RX_USER_WIDTH-1:0] rx_axis_tuser, - - /* - * GMII interface - */ - input wire [DATA_WIDTH-1:0] gmii_rxd, - input wire gmii_rx_dv, - input wire gmii_rx_er, - output wire [DATA_WIDTH-1:0] gmii_txd, - output wire gmii_tx_en, - output wire gmii_tx_er, - - /* - * PTP - */ - input wire [PTP_TS_WIDTH-1:0] tx_ptp_ts, - input wire [PTP_TS_WIDTH-1:0] rx_ptp_ts, - output wire [PTP_TS_WIDTH-1:0] tx_axis_ptp_ts, - output wire [TX_PTP_TAG_WIDTH-1:0] tx_axis_ptp_ts_tag, - output wire tx_axis_ptp_ts_valid, - - /* - * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) - */ - input wire tx_lfc_req, - input wire tx_lfc_resend, - input wire rx_lfc_en, - output wire rx_lfc_req, - input wire rx_lfc_ack, - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) - */ - input wire [7:0] tx_pfc_req, - input wire tx_pfc_resend, - input wire [7:0] rx_pfc_en, - output wire [7:0] rx_pfc_req, - input wire [7:0] rx_pfc_ack, - - /* - * Pause interface - */ - input wire tx_lfc_pause_en, - input wire tx_pause_req, - output wire tx_pause_ack, - - /* - * Control - */ - input wire rx_clk_enable, - input wire tx_clk_enable, - input wire rx_mii_select, - input wire tx_mii_select, - - /* - * Status - */ - output wire tx_start_packet, - output wire tx_error_underflow, - output wire rx_start_packet, - output wire rx_error_bad_frame, - output wire rx_error_bad_fcs, - output wire stat_tx_mcf, - output wire stat_rx_mcf, - output wire stat_tx_lfc_pkt, - output wire stat_tx_lfc_xon, - output wire stat_tx_lfc_xoff, - output wire stat_tx_lfc_paused, - output wire stat_tx_pfc_pkt, - output wire [7:0] stat_tx_pfc_xon, - output wire [7:0] stat_tx_pfc_xoff, - output wire [7:0] stat_tx_pfc_paused, - output wire stat_rx_lfc_pkt, - output wire stat_rx_lfc_xon, - output wire stat_rx_lfc_xoff, - output wire stat_rx_lfc_paused, - output wire stat_rx_pfc_pkt, - output wire [7:0] stat_rx_pfc_xon, - output wire [7:0] stat_rx_pfc_xoff, - output wire [7:0] stat_rx_pfc_paused, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - input wire cfg_rx_enable, - input wire [47:0] cfg_mcf_rx_eth_dst_mcast, - input wire cfg_mcf_rx_check_eth_dst_mcast, - input wire [47:0] cfg_mcf_rx_eth_dst_ucast, - input wire cfg_mcf_rx_check_eth_dst_ucast, - input wire [47:0] cfg_mcf_rx_eth_src, - input wire cfg_mcf_rx_check_eth_src, - input wire [15:0] cfg_mcf_rx_eth_type, - input wire [15:0] cfg_mcf_rx_opcode_lfc, - input wire cfg_mcf_rx_check_opcode_lfc, - input wire [15:0] cfg_mcf_rx_opcode_pfc, - input wire cfg_mcf_rx_check_opcode_pfc, - input wire cfg_mcf_rx_forward, - input wire cfg_mcf_rx_enable, - input wire [47:0] cfg_tx_lfc_eth_dst, - input wire [47:0] cfg_tx_lfc_eth_src, - input wire [15:0] cfg_tx_lfc_eth_type, - input wire [15:0] cfg_tx_lfc_opcode, - input wire cfg_tx_lfc_en, - input wire [15:0] cfg_tx_lfc_quanta, - input wire [15:0] cfg_tx_lfc_refresh, - input wire [47:0] cfg_tx_pfc_eth_dst, - input wire [47:0] cfg_tx_pfc_eth_src, - input wire [15:0] cfg_tx_pfc_eth_type, - input wire [15:0] cfg_tx_pfc_opcode, - input wire cfg_tx_pfc_en, - input wire [8*16-1:0] cfg_tx_pfc_quanta, - input wire [8*16-1:0] cfg_tx_pfc_refresh, - input wire [15:0] cfg_rx_lfc_opcode, - input wire cfg_rx_lfc_en, - input wire [15:0] cfg_rx_pfc_opcode, - input wire cfg_rx_pfc_en -); - -parameter MAC_CTRL_ENABLE = PAUSE_ENABLE || PFC_ENABLE; -parameter TX_USER_WIDTH_INT = MAC_CTRL_ENABLE ? (PTP_TS_ENABLE ? (TX_PTP_TAG_ENABLE ? TX_PTP_TAG_WIDTH : 0) + 1 : 0) + 1 : TX_USER_WIDTH; - -wire [DATA_WIDTH-1:0] tx_axis_tdata_int; -wire tx_axis_tvalid_int; -wire tx_axis_tready_int; -wire tx_axis_tlast_int; -wire [TX_USER_WIDTH_INT-1:0] tx_axis_tuser_int; - -wire [DATA_WIDTH-1:0] rx_axis_tdata_int; -wire rx_axis_tvalid_int; -wire rx_axis_tlast_int; -wire [RX_USER_WIDTH-1:0] rx_axis_tuser_int; - -axis_gmii_rx #( - .DATA_WIDTH(DATA_WIDTH), - .PTP_TS_ENABLE(PTP_TS_ENABLE), - .PTP_TS_WIDTH(PTP_TS_WIDTH), - .USER_WIDTH(RX_USER_WIDTH) -) -axis_gmii_rx_inst ( - .clk(rx_clk), - .rst(rx_rst), - .gmii_rxd(gmii_rxd), - .gmii_rx_dv(gmii_rx_dv), - .gmii_rx_er(gmii_rx_er), - .m_axis_tdata(rx_axis_tdata_int), - .m_axis_tvalid(rx_axis_tvalid_int), - .m_axis_tlast(rx_axis_tlast_int), - .m_axis_tuser(rx_axis_tuser_int), - .ptp_ts(rx_ptp_ts), - .clk_enable(rx_clk_enable), - .mii_select(rx_mii_select), - .cfg_rx_enable(cfg_rx_enable), - .start_packet(rx_start_packet), - .error_bad_frame(rx_error_bad_frame), - .error_bad_fcs(rx_error_bad_fcs) -); - -axis_gmii_tx #( - .DATA_WIDTH(DATA_WIDTH), - .ENABLE_PADDING(ENABLE_PADDING), - .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH), - .PTP_TS_ENABLE(PTP_TS_ENABLE), - .PTP_TS_WIDTH(PTP_TS_WIDTH), - .PTP_TS_CTRL_IN_TUSER(MAC_CTRL_ENABLE ? PTP_TS_ENABLE : TX_PTP_TS_CTRL_IN_TUSER), - .PTP_TAG_ENABLE(TX_PTP_TAG_ENABLE), - .PTP_TAG_WIDTH(TX_PTP_TAG_WIDTH), - .USER_WIDTH(TX_USER_WIDTH_INT) -) -axis_gmii_tx_inst ( - .clk(tx_clk), - .rst(tx_rst), - .s_axis_tdata(tx_axis_tdata_int), - .s_axis_tvalid(tx_axis_tvalid_int), - .s_axis_tready(tx_axis_tready_int), - .s_axis_tlast(tx_axis_tlast_int), - .s_axis_tuser(tx_axis_tuser_int), - .gmii_txd(gmii_txd), - .gmii_tx_en(gmii_tx_en), - .gmii_tx_er(gmii_tx_er), - .ptp_ts(tx_ptp_ts), - .m_axis_ptp_ts(tx_axis_ptp_ts), - .m_axis_ptp_ts_tag(tx_axis_ptp_ts_tag), - .m_axis_ptp_ts_valid(tx_axis_ptp_ts_valid), - .clk_enable(tx_clk_enable), - .mii_select(tx_mii_select), - .cfg_ifg(cfg_ifg), - .cfg_tx_enable(cfg_tx_enable), - .start_packet(tx_start_packet), - .error_underflow(tx_error_underflow) -); - -generate - -if (MAC_CTRL_ENABLE) begin : mac_ctrl - - localparam MCF_PARAMS_SIZE = PFC_ENABLE ? 18 : 2; - - wire tx_mcf_valid; - wire tx_mcf_ready; - wire [47:0] tx_mcf_eth_dst; - wire [47:0] tx_mcf_eth_src; - wire [15:0] tx_mcf_eth_type; - wire [15:0] tx_mcf_opcode; - wire [MCF_PARAMS_SIZE*8-1:0] tx_mcf_params; - - wire rx_mcf_valid; - wire [47:0] rx_mcf_eth_dst; - wire [47:0] rx_mcf_eth_src; - wire [15:0] rx_mcf_eth_type; - wire [15:0] rx_mcf_opcode; - wire [MCF_PARAMS_SIZE*8-1:0] rx_mcf_params; - - // terminate LFC pause requests from RX internally on TX side - wire tx_pause_req_int; - wire rx_lfc_ack_int; - - reg tx_lfc_req_sync_reg_1 = 1'b0; - reg tx_lfc_req_sync_reg_2 = 1'b0; - reg tx_lfc_req_sync_reg_3 = 1'b0; - - always @(posedge rx_clk or posedge rx_rst) begin - if (rx_rst) begin - tx_lfc_req_sync_reg_1 <= 1'b0; - end else begin - tx_lfc_req_sync_reg_1 <= rx_lfc_req; - end - end - - always @(posedge tx_clk or posedge tx_rst) begin - if (tx_rst) begin - tx_lfc_req_sync_reg_2 <= 1'b0; - tx_lfc_req_sync_reg_3 <= 1'b0; - end else begin - tx_lfc_req_sync_reg_2 <= tx_lfc_req_sync_reg_1; - tx_lfc_req_sync_reg_3 <= tx_lfc_req_sync_reg_2; - end - end - - reg rx_lfc_ack_sync_reg_1 = 1'b0; - reg rx_lfc_ack_sync_reg_2 = 1'b0; - reg rx_lfc_ack_sync_reg_3 = 1'b0; - - always @(posedge tx_clk or posedge tx_rst) begin - if (tx_rst) begin - rx_lfc_ack_sync_reg_1 <= 1'b0; - end else begin - rx_lfc_ack_sync_reg_1 <= tx_lfc_pause_en ? tx_pause_ack : 0; - end - end - - always @(posedge rx_clk or posedge rx_rst) begin - if (rx_rst) begin - rx_lfc_ack_sync_reg_2 <= 1'b0; - rx_lfc_ack_sync_reg_3 <= 1'b0; - end else begin - rx_lfc_ack_sync_reg_2 <= rx_lfc_ack_sync_reg_1; - rx_lfc_ack_sync_reg_3 <= rx_lfc_ack_sync_reg_2; - end - end - - assign tx_pause_req_int = tx_pause_req || (tx_lfc_pause_en ? tx_lfc_req_sync_reg_3 : 0); - - assign rx_lfc_ack_int = rx_lfc_ack || rx_lfc_ack_sync_reg_3; - - // handle PTP TS enable bit in tuser - wire [TX_USER_WIDTH_INT-1:0] tx_axis_tuser_in; - - if (PTP_TS_ENABLE && !TX_PTP_TS_CTRL_IN_TUSER) begin - assign tx_axis_tuser_in = {tx_axis_tuser[TX_USER_WIDTH-1:1], 1'b1, tx_axis_tuser[0]}; - end else begin - assign tx_axis_tuser_in = tx_axis_tuser; - end - - mac_ctrl_tx #( - .DATA_WIDTH(DATA_WIDTH), - .KEEP_ENABLE(0), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(TX_USER_WIDTH_INT), - .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE) - ) - mac_ctrl_tx_inst ( - .clk(tx_clk), - .rst(tx_rst), - - /* - * AXI stream input - */ - .s_axis_tdata(tx_axis_tdata), - .s_axis_tkeep(1'b1), - .s_axis_tvalid(tx_axis_tvalid), - .s_axis_tready(tx_axis_tready), - .s_axis_tlast(tx_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(tx_axis_tuser_in), - - /* - * AXI stream output - */ - .m_axis_tdata(tx_axis_tdata_int), - .m_axis_tkeep(), - .m_axis_tvalid(tx_axis_tvalid_int), - .m_axis_tready(tx_axis_tready_int), - .m_axis_tlast(tx_axis_tlast_int), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(tx_axis_tuser_int), - - /* - * MAC control frame interface - */ - .mcf_valid(tx_mcf_valid), - .mcf_ready(tx_mcf_ready), - .mcf_eth_dst(tx_mcf_eth_dst), - .mcf_eth_src(tx_mcf_eth_src), - .mcf_eth_type(tx_mcf_eth_type), - .mcf_opcode(tx_mcf_opcode), - .mcf_params(tx_mcf_params), - .mcf_id(0), - .mcf_dest(0), - .mcf_user(0), - - /* - * Pause interface - */ - .tx_pause_req(tx_pause_req_int), - .tx_pause_ack(tx_pause_ack), - - /* - * Status - */ - .stat_tx_mcf(stat_tx_mcf) - ); - - mac_ctrl_rx #( - .DATA_WIDTH(DATA_WIDTH), - .KEEP_ENABLE(0), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(RX_USER_WIDTH), - .USE_READY(0), - .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE) - ) - mac_ctrl_rx_inst ( - .clk(rx_clk), - .rst(rx_rst), - - /* - * AXI stream input - */ - .s_axis_tdata(rx_axis_tdata_int), - .s_axis_tkeep(1'b1), - .s_axis_tvalid(rx_axis_tvalid_int), - .s_axis_tready(), - .s_axis_tlast(rx_axis_tlast_int), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(rx_axis_tuser_int), - - /* - * AXI stream output - */ - .m_axis_tdata(rx_axis_tdata), - .m_axis_tkeep(), - .m_axis_tvalid(rx_axis_tvalid), - .m_axis_tready(1'b1), - .m_axis_tlast(rx_axis_tlast), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(rx_axis_tuser), - - /* - * MAC control frame interface - */ - .mcf_valid(rx_mcf_valid), - .mcf_eth_dst(rx_mcf_eth_dst), - .mcf_eth_src(rx_mcf_eth_src), - .mcf_eth_type(rx_mcf_eth_type), - .mcf_opcode(rx_mcf_opcode), - .mcf_params(rx_mcf_params), - .mcf_id(), - .mcf_dest(), - .mcf_user(), - - /* - * Configuration - */ - .cfg_mcf_rx_eth_dst_mcast(cfg_mcf_rx_eth_dst_mcast), - .cfg_mcf_rx_check_eth_dst_mcast(cfg_mcf_rx_check_eth_dst_mcast), - .cfg_mcf_rx_eth_dst_ucast(cfg_mcf_rx_eth_dst_ucast), - .cfg_mcf_rx_check_eth_dst_ucast(cfg_mcf_rx_check_eth_dst_ucast), - .cfg_mcf_rx_eth_src(cfg_mcf_rx_eth_src), - .cfg_mcf_rx_check_eth_src(cfg_mcf_rx_check_eth_src), - .cfg_mcf_rx_eth_type(cfg_mcf_rx_eth_type), - .cfg_mcf_rx_opcode_lfc(cfg_mcf_rx_opcode_lfc), - .cfg_mcf_rx_check_opcode_lfc(cfg_mcf_rx_check_opcode_lfc), - .cfg_mcf_rx_opcode_pfc(cfg_mcf_rx_opcode_pfc), - .cfg_mcf_rx_check_opcode_pfc(cfg_mcf_rx_check_opcode_pfc), - .cfg_mcf_rx_forward(cfg_mcf_rx_forward), - .cfg_mcf_rx_enable(cfg_mcf_rx_enable), - - /* - * Status - */ - .stat_rx_mcf(stat_rx_mcf) - ); - - mac_pause_ctrl_tx #( - .MCF_PARAMS_SIZE(MCF_PARAMS_SIZE), - .PFC_ENABLE(PFC_ENABLE) - ) - mac_pause_ctrl_tx_inst ( - .clk(tx_clk), - .rst(tx_rst), - - /* - * MAC control frame interface - */ - .mcf_valid(tx_mcf_valid), - .mcf_ready(tx_mcf_ready), - .mcf_eth_dst(tx_mcf_eth_dst), - .mcf_eth_src(tx_mcf_eth_src), - .mcf_eth_type(tx_mcf_eth_type), - .mcf_opcode(tx_mcf_opcode), - .mcf_params(tx_mcf_params), - - /* - * Pause (IEEE 802.3 annex 31B) - */ - .tx_lfc_req(tx_lfc_req), - .tx_lfc_resend(tx_lfc_resend), - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) - */ - .tx_pfc_req(tx_pfc_req), - .tx_pfc_resend(tx_pfc_resend), - - /* - * Configuration - */ - .cfg_tx_lfc_eth_dst(cfg_tx_lfc_eth_dst), - .cfg_tx_lfc_eth_src(cfg_tx_lfc_eth_src), - .cfg_tx_lfc_eth_type(cfg_tx_lfc_eth_type), - .cfg_tx_lfc_opcode(cfg_tx_lfc_opcode), - .cfg_tx_lfc_en(cfg_tx_lfc_en), - .cfg_tx_lfc_quanta(cfg_tx_lfc_quanta), - .cfg_tx_lfc_refresh(cfg_tx_lfc_refresh), - .cfg_tx_pfc_eth_dst(cfg_tx_pfc_eth_dst), - .cfg_tx_pfc_eth_src(cfg_tx_pfc_eth_src), - .cfg_tx_pfc_eth_type(cfg_tx_pfc_eth_type), - .cfg_tx_pfc_opcode(cfg_tx_pfc_opcode), - .cfg_tx_pfc_en(cfg_tx_pfc_en), - .cfg_tx_pfc_quanta(cfg_tx_pfc_quanta), - .cfg_tx_pfc_refresh(cfg_tx_pfc_refresh), - .cfg_quanta_step(tx_mii_select ? (4*256)/512 : (8*256)/512), - .cfg_quanta_clk_en(tx_clk_enable), - - /* - * Status - */ - .stat_tx_lfc_pkt(stat_tx_lfc_pkt), - .stat_tx_lfc_xon(stat_tx_lfc_xon), - .stat_tx_lfc_xoff(stat_tx_lfc_xoff), - .stat_tx_lfc_paused(stat_tx_lfc_paused), - .stat_tx_pfc_pkt(stat_tx_pfc_pkt), - .stat_tx_pfc_xon(stat_tx_pfc_xon), - .stat_tx_pfc_xoff(stat_tx_pfc_xoff), - .stat_tx_pfc_paused(stat_tx_pfc_paused) - ); - - mac_pause_ctrl_rx #( - .MCF_PARAMS_SIZE(18), - .PFC_ENABLE(PFC_ENABLE) - ) - mac_pause_ctrl_rx_inst ( - .clk(rx_clk), - .rst(rx_rst), - - /* - * MAC control frame interface - */ - .mcf_valid(rx_mcf_valid), - .mcf_eth_dst(rx_mcf_eth_dst), - .mcf_eth_src(rx_mcf_eth_src), - .mcf_eth_type(rx_mcf_eth_type), - .mcf_opcode(rx_mcf_opcode), - .mcf_params(rx_mcf_params), - - /* - * Pause (IEEE 802.3 annex 31B) - */ - .rx_lfc_en(rx_lfc_en), - .rx_lfc_req(rx_lfc_req), - .rx_lfc_ack(rx_lfc_ack_int), - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) - */ - .rx_pfc_en(rx_pfc_en), - .rx_pfc_req(rx_pfc_req), - .rx_pfc_ack(rx_pfc_ack), - - /* - * Configuration - */ - .cfg_rx_lfc_opcode(cfg_rx_lfc_opcode), - .cfg_rx_lfc_en(cfg_rx_lfc_en), - .cfg_rx_pfc_opcode(cfg_rx_pfc_opcode), - .cfg_rx_pfc_en(cfg_rx_pfc_en), - .cfg_quanta_step(rx_mii_select ? (4*256)/512 : (8*256)/512), - .cfg_quanta_clk_en(rx_clk_enable), - - /* - * Status - */ - .stat_rx_lfc_pkt(stat_rx_lfc_pkt), - .stat_rx_lfc_xon(stat_rx_lfc_xon), - .stat_rx_lfc_xoff(stat_rx_lfc_xoff), - .stat_rx_lfc_paused(stat_rx_lfc_paused), - .stat_rx_pfc_pkt(stat_rx_pfc_pkt), - .stat_rx_pfc_xon(stat_rx_pfc_xon), - .stat_rx_pfc_xoff(stat_rx_pfc_xoff), - .stat_rx_pfc_paused(stat_rx_pfc_paused) - ); - -end else begin - - assign tx_axis_tdata_int = tx_axis_tdata; - assign tx_axis_tvalid_int = tx_axis_tvalid; - assign tx_axis_tready = tx_axis_tready_int; - assign tx_axis_tlast_int = tx_axis_tlast; - assign tx_axis_tuser_int = tx_axis_tuser; - - assign rx_axis_tdata = rx_axis_tdata_int; - assign rx_axis_tvalid = rx_axis_tvalid_int; - assign rx_axis_tlast = rx_axis_tlast_int; - assign rx_axis_tuser = rx_axis_tuser_int; - - assign rx_lfc_req = 0; - assign rx_pfc_req = 0; - assign tx_pause_ack = 0; - - assign stat_tx_mcf = 0; - assign stat_rx_mcf = 0; - assign stat_tx_lfc_pkt = 0; - assign stat_tx_lfc_xon = 0; - assign stat_tx_lfc_xoff = 0; - assign stat_tx_lfc_paused = 0; - assign stat_tx_pfc_pkt = 0; - assign stat_tx_pfc_xon = 0; - assign stat_tx_pfc_xoff = 0; - assign stat_tx_pfc_paused = 0; - assign stat_rx_lfc_pkt = 0; - assign stat_rx_lfc_xon = 0; - assign stat_rx_lfc_xoff = 0; - assign stat_rx_lfc_paused = 0; - assign stat_rx_pfc_pkt = 0; - assign stat_rx_pfc_xon = 0; - assign stat_rx_pfc_xoff = 0; - assign stat_rx_pfc_paused = 0; - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/eth_mac_mii.sv b/src/rvvi/eth_mac_mii.sv deleted file mode 100644 index 212f4b84a..000000000 --- a/src/rvvi/eth_mac_mii.sv +++ /dev/null @@ -1,175 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * 10M/100M Ethernet MAC with MII interface - */ -module eth_mac_mii # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2", - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64 -) -( - input wire rst, - output wire rx_clk, - output wire rx_rst, - output wire tx_clk, - output wire tx_rst, - - /* - * AXI input - */ - input wire [7:0] tx_axis_tdata, - input wire tx_axis_tvalid, - output wire tx_axis_tready, - input wire tx_axis_tlast, - input wire tx_axis_tuser, - - /* - * AXI output - */ - output wire [7:0] rx_axis_tdata, - output wire rx_axis_tvalid, - output wire rx_axis_tlast, - output wire rx_axis_tuser, - - /* - * MII interface - */ - input wire mii_rx_clk, - input wire [3:0] mii_rxd, - input wire mii_rx_dv, - input wire mii_rx_er, - input wire mii_tx_clk, - output wire [3:0] mii_txd, - output wire mii_tx_en, - output wire mii_tx_er, - - /* - * Status - */ - output wire tx_start_packet, - output wire tx_error_underflow, - output wire rx_start_packet, - output wire rx_error_bad_frame, - output wire rx_error_bad_fcs, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - input wire cfg_rx_enable -); - -wire [3:0] mac_mii_rxd; -wire mac_mii_rx_dv; -wire mac_mii_rx_er; -wire [3:0] mac_mii_txd; -wire mac_mii_tx_en; -wire mac_mii_tx_er; - -mii_phy_if #( - .TARGET(TARGET), - .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE) -) -mii_phy_if_inst ( - .rst(rst), - - .mac_mii_rx_clk(rx_clk), - .mac_mii_rx_rst(rx_rst), - .mac_mii_rxd(mac_mii_rxd), - .mac_mii_rx_dv(mac_mii_rx_dv), - .mac_mii_rx_er(mac_mii_rx_er), - .mac_mii_tx_clk(tx_clk), - .mac_mii_tx_rst(tx_rst), - .mac_mii_txd(mac_mii_txd), - .mac_mii_tx_en(mac_mii_tx_en), - .mac_mii_tx_er(mac_mii_tx_er), - - .phy_mii_rx_clk(mii_rx_clk), - .phy_mii_rxd(mii_rxd), - .phy_mii_rx_dv(mii_rx_dv), - .phy_mii_rx_er(mii_rx_er), - .phy_mii_tx_clk(mii_tx_clk), - .phy_mii_txd(mii_txd), - .phy_mii_tx_en(mii_tx_en), - .phy_mii_tx_er(mii_tx_er) -); - // *** there a bunch of missing pins -/* verilator lint_off PINMISSING */ -eth_mac_1g #( - .ENABLE_PADDING(ENABLE_PADDING), - .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH) -) -eth_mac_1g_inst ( - .tx_clk(tx_clk), - .tx_rst(tx_rst), - .rx_clk(rx_clk), - .rx_rst(rx_rst), - .tx_axis_tdata(tx_axis_tdata), - .tx_axis_tvalid(tx_axis_tvalid), - .tx_axis_tready(tx_axis_tready), - .tx_axis_tlast(tx_axis_tlast), - .tx_axis_tuser(tx_axis_tuser), - .rx_axis_tdata(rx_axis_tdata), - .rx_axis_tvalid(rx_axis_tvalid), - .rx_axis_tlast(rx_axis_tlast), - .rx_axis_tuser(rx_axis_tuser), - .gmii_rxd(mac_mii_rxd), - .gmii_rx_dv(mac_mii_rx_dv), - .gmii_rx_er(mac_mii_rx_er), - .gmii_txd(mac_mii_txd), - .gmii_tx_en(mac_mii_tx_en), - .gmii_tx_er(mac_mii_tx_er), - .rx_clk_enable(1'b1), - .tx_clk_enable(1'b1), - .rx_mii_select(1'b1), - .tx_mii_select(1'b1), - .tx_start_packet(tx_start_packet), - .tx_error_underflow(tx_error_underflow), - .rx_start_packet(rx_start_packet), - .rx_error_bad_frame(rx_error_bad_frame), - .rx_error_bad_fcs(rx_error_bad_fcs), - .cfg_ifg(cfg_ifg), - .cfg_tx_enable(cfg_tx_enable), - .cfg_rx_enable(cfg_rx_enable) -); -/* verilator lint_on PINMISSING */ - -endmodule - -`resetall diff --git a/src/rvvi/eth_mac_mii_fifo.sv b/src/rvvi/eth_mac_mii_fifo.sv deleted file mode 100644 index a285ceeed..000000000 --- a/src/rvvi/eth_mac_mii_fifo.sv +++ /dev/null @@ -1,339 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * 10M/100M Ethernet MAC with MII interface and TX and RX FIFOs - */ -module eth_mac_mii_fifo # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2", - parameter AXIS_DATA_WIDTH = 8, - parameter AXIS_KEEP_ENABLE = (AXIS_DATA_WIDTH>8), - parameter AXIS_KEEP_WIDTH = (AXIS_DATA_WIDTH/8), - parameter ENABLE_PADDING = 1, - parameter MIN_FRAME_LENGTH = 64, - parameter TX_FIFO_DEPTH = 4096, - parameter TX_FIFO_RAM_PIPELINE = 1, - parameter TX_FRAME_FIFO = 1, - parameter TX_DROP_OVERSIZE_FRAME = TX_FRAME_FIFO, - parameter TX_DROP_BAD_FRAME = TX_DROP_OVERSIZE_FRAME, - parameter TX_DROP_WHEN_FULL = 0, - parameter RX_FIFO_DEPTH = 4096, - parameter RX_FIFO_RAM_PIPELINE = 1, - parameter RX_FRAME_FIFO = 1, - parameter RX_DROP_OVERSIZE_FRAME = RX_FRAME_FIFO, - parameter RX_DROP_BAD_FRAME = RX_DROP_OVERSIZE_FRAME, - parameter RX_DROP_WHEN_FULL = RX_DROP_OVERSIZE_FRAME -) -( - input wire rst, - input wire logic_clk, - input wire logic_rst, - - /* - * AXI input - */ - input wire [AXIS_DATA_WIDTH-1:0] tx_axis_tdata, - input wire [AXIS_KEEP_WIDTH-1:0] tx_axis_tkeep, - input wire tx_axis_tvalid, - output wire tx_axis_tready, - input wire tx_axis_tlast, - input wire tx_axis_tuser, - - /* - * AXI output - */ - output wire [AXIS_DATA_WIDTH-1:0] rx_axis_tdata, - output wire [AXIS_KEEP_WIDTH-1:0] rx_axis_tkeep, - output wire rx_axis_tvalid, - input wire rx_axis_tready, - output wire rx_axis_tlast, - output wire rx_axis_tuser, - - /* - * MII interface - */ - input wire mii_rx_clk, - input wire [3:0] mii_rxd, - input wire mii_rx_dv, - input wire mii_rx_er, - input wire mii_tx_clk, - output wire [3:0] mii_txd, - output wire mii_tx_en, - output wire mii_tx_er, - - /* - * Status - */ - output wire tx_error_underflow, - output wire tx_fifo_overflow, - output wire tx_fifo_bad_frame, - output wire tx_fifo_good_frame, - output wire rx_error_bad_frame, - output wire rx_error_bad_fcs, - output wire rx_fifo_overflow, - output wire rx_fifo_bad_frame, - output wire rx_fifo_good_frame, - - /* - * Configuration - */ - input wire [7:0] cfg_ifg, - input wire cfg_tx_enable, - input wire cfg_rx_enable -); - -wire tx_clk; -wire rx_clk; -wire tx_rst; -wire rx_rst; - -wire [7:0] tx_fifo_axis_tdata; -wire tx_fifo_axis_tvalid; -wire tx_fifo_axis_tready; -wire tx_fifo_axis_tlast; -wire tx_fifo_axis_tuser; - -wire [7:0] rx_fifo_axis_tdata; -wire rx_fifo_axis_tvalid; -wire rx_fifo_axis_tlast; -wire rx_fifo_axis_tuser; - -// synchronize MAC status signals into logic clock domain -wire tx_error_underflow_int; - -reg [0:0] tx_sync_reg_1 = 1'b0; -reg [0:0] tx_sync_reg_2 = 1'b0; -reg [0:0] tx_sync_reg_3 = 1'b0; -reg [0:0] tx_sync_reg_4 = 1'b0; - -assign tx_error_underflow = tx_sync_reg_3[0] ^ tx_sync_reg_4[0]; - -always @(posedge tx_clk or posedge tx_rst) begin - if (tx_rst) begin - tx_sync_reg_1 <= 1'b0; - end else begin - tx_sync_reg_1 <= tx_sync_reg_1 ^ {tx_error_underflow_int}; - end -end - -always @(posedge logic_clk or posedge logic_rst) begin - if (logic_rst) begin - tx_sync_reg_2 <= 1'b0; - tx_sync_reg_3 <= 1'b0; - tx_sync_reg_4 <= 1'b0; - end else begin - tx_sync_reg_2 <= tx_sync_reg_1; - tx_sync_reg_3 <= tx_sync_reg_2; - tx_sync_reg_4 <= tx_sync_reg_3; - end -end - -wire rx_error_bad_frame_int; -wire rx_error_bad_fcs_int; - -reg [1:0] rx_sync_reg_1 = 2'd0; -reg [1:0] rx_sync_reg_2 = 2'd0; -reg [1:0] rx_sync_reg_3 = 2'd0; -reg [1:0] rx_sync_reg_4 = 2'd0; - -assign rx_error_bad_frame = rx_sync_reg_3[0] ^ rx_sync_reg_4[0]; -assign rx_error_bad_fcs = rx_sync_reg_3[1] ^ rx_sync_reg_4[1]; - -always @(posedge rx_clk or posedge rx_rst) begin - if (rx_rst) begin - rx_sync_reg_1 <= 2'd0; - end else begin - rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_error_bad_fcs_int, rx_error_bad_frame_int}; - end -end - -always @(posedge logic_clk or posedge logic_rst) begin - if (logic_rst) begin - rx_sync_reg_2 <= 2'd0; - rx_sync_reg_3 <= 2'd0; - rx_sync_reg_4 <= 2'd0; - end else begin - rx_sync_reg_2 <= rx_sync_reg_1; - rx_sync_reg_3 <= rx_sync_reg_2; - rx_sync_reg_4 <= rx_sync_reg_3; - end -end - - // *** there are a bunch of missing pins - /* verilator lint_off PINMISSING */ -eth_mac_mii #( - .TARGET(TARGET), - .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), - .ENABLE_PADDING(ENABLE_PADDING), - .MIN_FRAME_LENGTH(MIN_FRAME_LENGTH) -) -eth_mac_1g_mii_inst ( - .rst(rst), - .tx_clk(tx_clk), - .tx_rst(tx_rst), - .rx_clk(rx_clk), - .rx_rst(rx_rst), - .tx_axis_tdata(tx_fifo_axis_tdata), - .tx_axis_tvalid(tx_fifo_axis_tvalid), - .tx_axis_tready(tx_fifo_axis_tready), - .tx_axis_tlast(tx_fifo_axis_tlast), - .tx_axis_tuser(tx_fifo_axis_tuser), - .rx_axis_tdata(rx_fifo_axis_tdata), - .rx_axis_tvalid(rx_fifo_axis_tvalid), - .rx_axis_tlast(rx_fifo_axis_tlast), - .rx_axis_tuser(rx_fifo_axis_tuser), - .mii_rx_clk(mii_rx_clk), - .mii_rxd(mii_rxd), - .mii_rx_dv(mii_rx_dv), - .mii_rx_er(mii_rx_er), - .mii_tx_clk(mii_tx_clk), - .mii_txd(mii_txd), - .mii_tx_en(mii_tx_en), - .mii_tx_er(mii_tx_er), - .tx_error_underflow(tx_error_underflow_int), - .rx_error_bad_frame(rx_error_bad_frame_int), - .rx_error_bad_fcs(rx_error_bad_fcs_int), - .cfg_ifg(cfg_ifg), - .cfg_tx_enable(cfg_tx_enable), - .cfg_rx_enable(cfg_rx_enable) -); - -axis_async_fifo_adapter #( - .DEPTH(TX_FIFO_DEPTH), - .S_DATA_WIDTH(AXIS_DATA_WIDTH), - .S_KEEP_ENABLE(AXIS_KEEP_ENABLE), - .S_KEEP_WIDTH(AXIS_KEEP_WIDTH), - .M_DATA_WIDTH(8), - .M_KEEP_ENABLE(0), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(1), - .RAM_PIPELINE(TX_FIFO_RAM_PIPELINE), - .FRAME_FIFO(TX_FRAME_FIFO), - .USER_BAD_FRAME_VALUE(1'b1), - .USER_BAD_FRAME_MASK(1'b1), - .DROP_OVERSIZE_FRAME(TX_DROP_OVERSIZE_FRAME), - .DROP_BAD_FRAME(TX_DROP_BAD_FRAME), - .DROP_WHEN_FULL(TX_DROP_WHEN_FULL) -) -tx_fifo ( - // AXI input - .s_clk(logic_clk), - .s_rst(logic_rst), - .s_axis_tdata(tx_axis_tdata), - .s_axis_tkeep(tx_axis_tkeep), - .s_axis_tvalid(tx_axis_tvalid), - .s_axis_tready(tx_axis_tready), - .s_axis_tlast(tx_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(tx_axis_tuser), - // AXI output - .m_clk(tx_clk), - .m_rst(tx_rst), - .m_axis_tdata(tx_fifo_axis_tdata), - .m_axis_tkeep(), - .m_axis_tvalid(tx_fifo_axis_tvalid), - .m_axis_tready(tx_fifo_axis_tready), - .m_axis_tlast(tx_fifo_axis_tlast), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(tx_fifo_axis_tuser), - // Status - .s_status_overflow(tx_fifo_overflow), - .s_status_bad_frame(tx_fifo_bad_frame), - .s_status_good_frame(tx_fifo_good_frame), - .m_status_overflow(), - .m_status_bad_frame(), - .m_status_good_frame() -); - -axis_async_fifo_adapter #( - .DEPTH(RX_FIFO_DEPTH), - .S_DATA_WIDTH(8), - .S_KEEP_ENABLE(0), - .M_DATA_WIDTH(AXIS_DATA_WIDTH), - .M_KEEP_ENABLE(AXIS_KEEP_ENABLE), - .M_KEEP_WIDTH(AXIS_KEEP_WIDTH), - .ID_ENABLE(0), - .DEST_ENABLE(0), - .USER_ENABLE(1), - .USER_WIDTH(1), - .RAM_PIPELINE(RX_FIFO_RAM_PIPELINE), - .FRAME_FIFO(RX_FRAME_FIFO), - .USER_BAD_FRAME_VALUE(1'b1), - .USER_BAD_FRAME_MASK(1'b1), - .DROP_OVERSIZE_FRAME(RX_DROP_OVERSIZE_FRAME), - .DROP_BAD_FRAME(RX_DROP_BAD_FRAME), - .DROP_WHEN_FULL(RX_DROP_WHEN_FULL) -) -rx_fifo ( - // AXI input - .s_clk(rx_clk), - .s_rst(rx_rst), - .s_axis_tdata(rx_fifo_axis_tdata), - .s_axis_tkeep(0), - .s_axis_tvalid(rx_fifo_axis_tvalid), - .s_axis_tready(), - .s_axis_tlast(rx_fifo_axis_tlast), - .s_axis_tid(0), - .s_axis_tdest(0), - .s_axis_tuser(rx_fifo_axis_tuser), - // AXI output - .m_clk(logic_clk), - .m_rst(logic_rst), - .m_axis_tdata(rx_axis_tdata), - .m_axis_tkeep(rx_axis_tkeep), - .m_axis_tvalid(rx_axis_tvalid), - .m_axis_tready(rx_axis_tready), - .m_axis_tlast(rx_axis_tlast), - .m_axis_tid(), - .m_axis_tdest(), - .m_axis_tuser(rx_axis_tuser), - // Status - .s_status_overflow(), - .s_status_bad_frame(), - .s_status_good_frame(), - .m_status_overflow(rx_fifo_overflow), - .m_status_bad_frame(rx_fifo_bad_frame), - .m_status_good_frame(rx_fifo_good_frame) -); -/* verilator lint_on PINMISSING */ - -endmodule - -`resetall diff --git a/src/rvvi/lfsr.sv b/src/rvvi/lfsr.sv deleted file mode 100644 index 4b404fe94..000000000 --- a/src/rvvi/lfsr.sv +++ /dev/null @@ -1,446 +0,0 @@ -/* - -Copyright (c) 2016-2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * Parametrizable combinatorial parallel LFSR/CRC - */ -module lfsr # -( - // width of LFSR - parameter LFSR_WIDTH = 31, - // LFSR polynomial - parameter LFSR_POLY = 31'h10000001, - // LFSR configuration: "GALOIS", "FIBONACCI" - parameter LFSR_CONFIG = "FIBONACCI", - // LFSR feed forward enable - parameter LFSR_FEED_FORWARD = 0, - // bit-reverse input and output - parameter REVERSE = 0, - // width of data input - parameter DATA_WIDTH = 8, - // implementation style: "AUTO", "LOOP", "REDUCTION" - parameter STYLE = "AUTO" -) -( - input wire [DATA_WIDTH-1:0] data_in, - input wire [LFSR_WIDTH-1:0] state_in, - output wire [DATA_WIDTH-1:0] data_out, - output wire [LFSR_WIDTH-1:0] state_out -); - -/* - -Fully parametrizable combinatorial parallel LFSR/CRC module. Implements an unrolled LFSR -next state computation, shifting DATA_WIDTH bits per pass through the module. Input data -is XORed with LFSR feedback path, tie data_in to zero if this is not required. - -Works in two parts: statically computes a set of bit masks, then uses these bit masks to -select bits for XORing to compute the next state. - -Ports: - -data_in - -Data bits to be shifted through the LFSR (DATA_WIDTH bits) - -state_in - -LFSR/CRC current state input (LFSR_WIDTH bits) - -data_out - -Data bits shifted out of LFSR (DATA_WIDTH bits) - -state_out - -LFSR/CRC next state output (LFSR_WIDTH bits) - -Parameters: - -LFSR_WIDTH - -Specify width of LFSR/CRC register - -LFSR_POLY - -Specify the LFSR/CRC polynomial in hex format. For example, the polynomial - -x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 - -would be represented as - -32'h04c11db7 - -Note that the largest term (x^32) is suppressed. This term is generated automatically based -on LFSR_WIDTH. - -LFSR_CONFIG - -Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used -for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators, -scramblers, and descrambers, while Galois is generally used for cyclic redundancy check -generators and checkers. - -Fibonacci style (example for 64b66b scrambler, 0x8000000001) - - DIN (LSB first) - | - V - (+)<---------------------------(+)<-----------------------------. - | ^ | - | .----. .----. .----. | .----. .----. .----. | - +->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--' - | '----' '----' '----' '----' '----' '----' - V - DOUT - -Galois style (example for CRC16, 0x8005) - - ,-------------------+-------------------------+----------(+)<-- DIN (MSB first) - | | | ^ - | .----. .----. V .----. .----. V .----. | - `->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT - '----' '----' '----' '----' '----' - -LFSR_FEED_FORWARD - -Generate feed forward instead of feed back LFSR. Enable this for PRBS checking and self- -synchronous descrambling. - -Fibonacci feed-forward style (example for 64b66b descrambler, 0x8000000001) - - DIN (LSB first) - | - | .----. .----. .----. .----. .----. .----. - +->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--. - | '----' '----' '----' | '----' '----' '----' | - | V | - (+)<---------------------------(+)------------------------------' - | - V - DOUT - -Galois feed-forward style - - ,-------------------+-------------------------+------------+--- DIN (MSB first) - | | | | - | .----. .----. V .----. .----. V .----. V - `->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |->(+)-> DOUT - '----' '----' '----' '----' '----' - -REVERSE - -Bit-reverse LFSR input and output. Shifts MSB first by default, set REVERSE for LSB first. - -DATA_WIDTH - -Specify width of input and output data bus. The module will perform one shift per input -data bit, so if the input data bus is not required tie data_in to zero and set DATA_WIDTH -to the required number of shifts per clock cycle. - -STYLE - -Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO" -is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate -directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate -and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog -reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction -operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in -Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing -problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO" -will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey -synthesis translate directives. - -Settings for common LFSR/CRC implementations: - -Name Configuration Length Polynomial Initial value Notes -CRC16-IBM Galois, bit-reverse 16 16'h8005 16'hffff -CRC16-CCITT Galois 16 16'h1021 16'h1d0f -CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output -CRC32C Galois, bit-reverse 32 32'h1edc6f41 32'hffffffff iSCSI, Intel CRC32 instruction; invert final output -PRBS6 Fibonacci 6 6'h21 any -PRBS7 Fibonacci 7 7'h41 any -PRBS9 Fibonacci 9 9'h021 any ITU V.52 -PRBS10 Fibonacci 10 10'h081 any ITU -PRBS11 Fibonacci 11 11'h201 any ITU O.152 -PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152 -PRBS17 Fibonacci 17 17'h04001 any -PRBS20 Fibonacci 20 20'h00009 any ITU V.57 -PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151 -PRBS29 Fibonacci, inverted 29 29'h08000001 any -PRBS31 Fibonacci, inverted 31 31'h10000001 any -64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet -128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3 - -*/ - -function [LFSR_WIDTH+DATA_WIDTH-1:0] lfsr_mask(input [31:0] index); - reg [LFSR_WIDTH-1:0] lfsr_mask_state[LFSR_WIDTH-1:0]; - reg [DATA_WIDTH-1:0] lfsr_mask_data[LFSR_WIDTH-1:0]; - reg [LFSR_WIDTH-1:0] output_mask_state[DATA_WIDTH-1:0]; - reg [DATA_WIDTH-1:0] output_mask_data[DATA_WIDTH-1:0]; - - reg [LFSR_WIDTH-1:0] state_val; - reg [DATA_WIDTH-1:0] data_val; - - reg [DATA_WIDTH-1:0] data_mask; - - integer i, j; - - begin - // init bit masks - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - lfsr_mask_state[i] = 0; - lfsr_mask_state[i][i] = 1'b1; - lfsr_mask_data[i] = 0; - end - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - output_mask_state[i] = 0; - if (i < LFSR_WIDTH) begin - output_mask_state[i][i] = 1'b1; - end - output_mask_data[i] = 0; - end - - // simulate shift register - if (LFSR_CONFIG == "FIBONACCI") begin - // Fibonacci configuration - for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin - // determine shift in value - // current value in last FF, XOR with input data bit (MSB first) - state_val = lfsr_mask_state[LFSR_WIDTH-1]; - data_val = lfsr_mask_data[LFSR_WIDTH-1]; - data_val = data_val ^ data_mask; - - // add XOR inputs from correct indicies - for (j = 1; j < LFSR_WIDTH; j = j + 1) begin - if ((LFSR_POLY >> j) & 1) begin - state_val = lfsr_mask_state[j-1] ^ state_val; - data_val = lfsr_mask_data[j-1] ^ data_val; - end - end - - // shift - for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin - lfsr_mask_state[j] = lfsr_mask_state[j-1]; - lfsr_mask_data[j] = lfsr_mask_data[j-1]; - end - for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin - output_mask_state[j] = output_mask_state[j-1]; - output_mask_data[j] = output_mask_data[j-1]; - end - output_mask_state[0] = state_val; - output_mask_data[0] = data_val; - if (LFSR_FEED_FORWARD) begin - // only shift in new input data - state_val = {LFSR_WIDTH{1'b0}}; - data_val = data_mask; - end - lfsr_mask_state[0] = state_val; - lfsr_mask_data[0] = data_val; - end - end else if (LFSR_CONFIG == "GALOIS") begin - // Galois configuration - for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin - // determine shift in value - // current value in last FF, XOR with input data bit (MSB first) - state_val = lfsr_mask_state[LFSR_WIDTH-1]; - data_val = lfsr_mask_data[LFSR_WIDTH-1]; - data_val = data_val ^ data_mask; - - // shift - for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin - lfsr_mask_state[j] = lfsr_mask_state[j-1]; - lfsr_mask_data[j] = lfsr_mask_data[j-1]; - end - for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin - output_mask_state[j] = output_mask_state[j-1]; - output_mask_data[j] = output_mask_data[j-1]; - end - output_mask_state[0] = state_val; - output_mask_data[0] = data_val; - if (LFSR_FEED_FORWARD) begin - // only shift in new input data - state_val = {LFSR_WIDTH{1'b0}}; - data_val = data_mask; - end - lfsr_mask_state[0] = state_val; - lfsr_mask_data[0] = data_val; - - // add XOR inputs at correct indicies - for (j = 1; j < LFSR_WIDTH; j = j + 1) begin - if ((LFSR_POLY >> j) & 1) begin - lfsr_mask_state[j] = lfsr_mask_state[j] ^ state_val; - lfsr_mask_data[j] = lfsr_mask_data[j] ^ data_val; - end - end - end - end else begin - $error("Error: unknown configuration setting!"); - $finish; - end - - // reverse bits if selected - if (REVERSE) begin - if (index < LFSR_WIDTH) begin - state_val = 0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - state_val[i] = lfsr_mask_state[LFSR_WIDTH-index-1][LFSR_WIDTH-i-1]; - end - - data_val = 0; - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - data_val[i] = lfsr_mask_data[LFSR_WIDTH-index-1][DATA_WIDTH-i-1]; - end - end else begin - state_val = 0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - state_val[i] = output_mask_state[DATA_WIDTH-(index-LFSR_WIDTH)-1][LFSR_WIDTH-i-1]; - end - - data_val = 0; - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - data_val[i] = output_mask_data[DATA_WIDTH-(index-LFSR_WIDTH)-1][DATA_WIDTH-i-1]; - end - end - end else begin - if (index < LFSR_WIDTH) begin - state_val = lfsr_mask_state[index]; - data_val = lfsr_mask_data[index]; - end else begin - state_val = output_mask_state[index-LFSR_WIDTH]; - data_val = output_mask_data[index-LFSR_WIDTH]; - end - end - lfsr_mask = {data_val, state_val}; - end -endfunction - -// synthesis translate_off -`define SIMULATION -// synthesis translate_on - -`ifdef SIMULATION -// "AUTO" style is "REDUCTION" for faster simulation -parameter STYLE_INT = (STYLE == "AUTO") ? "REDUCTION" : STYLE; -`else -// "AUTO" style is "LOOP" for better synthesis result -parameter STYLE_INT = (STYLE == "AUTO") ? "LOOP" : STYLE; -`endif - -genvar n; - -generate - -if (STYLE_INT == "REDUCTION") begin - - // use Verilog reduction operator - // fast in iverilog - // significantly larger than generated code with ISE (inferred wide XORs may be tripping up optimizer) - // slightly smaller than generated code with Quartus - // --> better for simulation - - for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n); - assign state_out[n] = ^({data_in, state_in} & mask); - end - for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH); - assign data_out[n] = ^({data_in, state_in} & mask); - end - -end else if (STYLE_INT == "LOOP") begin - - // use nested loops - // very slow in iverilog - // slightly smaller than generated code with ISE - // same size as generated code with Quartus - // --> better for synthesis - - for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n); - - reg state_reg; - - assign state_out[n] = state_reg; - - integer i; - - always @* begin - state_reg = 1'b0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - if (mask[i]) begin - state_reg = state_reg ^ state_in[i]; - end - end - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - if (mask[i+LFSR_WIDTH]) begin - state_reg = state_reg ^ data_in[i]; - end - end - end - end - for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data - wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH); - - reg data_reg; - - assign data_out[n] = data_reg; - - integer i; - - always @* begin - data_reg = 1'b0; - for (i = 0; i < LFSR_WIDTH; i = i + 1) begin - if (mask[i]) begin - data_reg = data_reg ^ state_in[i]; - end - end - for (i = 0; i < DATA_WIDTH; i = i + 1) begin - if (mask[i+LFSR_WIDTH]) begin - data_reg = data_reg ^ data_in[i]; - end - end - end - end - -end else begin - - initial begin - $error("Error: unknown style setting!"); - $finish; - end - -end - -endgenerate - -endmodule - -`resetall diff --git a/src/rvvi/mac_ctrl_rx.sv b/src/rvvi/mac_ctrl_rx.sv deleted file mode 100644 index f7171887b..000000000 --- a/src/rvvi/mac_ctrl_rx.sv +++ /dev/null @@ -1,447 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * MAC control receive - */ -module mac_ctrl_rx # -( - parameter DATA_WIDTH = 8, - parameter KEEP_ENABLE = DATA_WIDTH>8, - parameter KEEP_WIDTH = DATA_WIDTH/8, - parameter ID_ENABLE = 0, - parameter ID_WIDTH = 8, - parameter DEST_ENABLE = 0, - parameter DEST_WIDTH = 8, - parameter USER_ENABLE = 1, - parameter USER_WIDTH = 1, - parameter USE_READY = 0, - parameter MCF_PARAMS_SIZE = 18 -) -( - input wire clk, - input wire rst, - - /* - * AXI stream input - */ - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI stream output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * MAC control frame interface - */ - output wire mcf_valid, - output wire [47:0] mcf_eth_dst, - output wire [47:0] mcf_eth_src, - output wire [15:0] mcf_eth_type, - output wire [15:0] mcf_opcode, - output wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - output wire [ID_WIDTH-1:0] mcf_id, - output wire [DEST_WIDTH-1:0] mcf_dest, - output wire [USER_WIDTH-1:0] mcf_user, - - /* - * Configuration - */ - input wire [47:0] cfg_mcf_rx_eth_dst_mcast, - input wire cfg_mcf_rx_check_eth_dst_mcast, - input wire [47:0] cfg_mcf_rx_eth_dst_ucast, - input wire cfg_mcf_rx_check_eth_dst_ucast, - input wire [47:0] cfg_mcf_rx_eth_src, - input wire cfg_mcf_rx_check_eth_src, - input wire [15:0] cfg_mcf_rx_eth_type, - input wire [15:0] cfg_mcf_rx_opcode_lfc, - input wire cfg_mcf_rx_check_opcode_lfc, - input wire [15:0] cfg_mcf_rx_opcode_pfc, - input wire cfg_mcf_rx_check_opcode_pfc, - input wire cfg_mcf_rx_forward, - input wire cfg_mcf_rx_enable, - - /* - * Status - */ - output wire stat_rx_mcf -); - -parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; - -parameter HDR_SIZE = 60; - -parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; - -parameter PTR_WIDTH = $clog2(CYCLE_COUNT); - -parameter OFFSET = HDR_SIZE % BYTE_LANES; - -// check configuration -initial begin - if (BYTE_LANES * 8 != DATA_WIDTH) begin - $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); - $finish; - end - - if (MCF_PARAMS_SIZE > 44) begin - $error("Error: Maximum MCF_PARAMS_SIZE is 44 bytes (instance %m)"); - $finish; - end -end - -/* - -MAC control frame - - Field Length - Destination MAC address 6 octets [01:80:C2:00:00:01] - Source MAC address 6 octets - Ethertype 2 octets [0x8808] - Opcode 2 octets - Parameters 0-44 octets - -This module manages the reception of MAC control frames. Incoming frames are -checked based on the ethertype and (optionally) MAC addresses. Matching control -frames are marked by setting tuser[0] on the data output and forwarded through -a separate interface for processing. - -*/ - -reg read_mcf_reg = 1'b1, read_mcf_next; -reg mcf_frame_reg = 1'b0, mcf_frame_next; -reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; - -reg s_axis_tready_reg = 1'b0, s_axis_tready_next; - -// internal datapath -reg [DATA_WIDTH-1:0] m_axis_tdata_int; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; -reg m_axis_tvalid_int; -reg m_axis_tready_int_reg = 1'b0; -reg m_axis_tlast_int; -reg [ID_WIDTH-1:0] m_axis_tid_int; -reg [DEST_WIDTH-1:0] m_axis_tdest_int; -reg [USER_WIDTH-1:0] m_axis_tuser_int; -wire m_axis_tready_int_early; - -reg mcf_valid_reg = 0, mcf_valid_next; -reg [47:0] mcf_eth_dst_reg = 0, mcf_eth_dst_next; -reg [47:0] mcf_eth_src_reg = 0, mcf_eth_src_next; -reg [15:0] mcf_eth_type_reg = 0, mcf_eth_type_next; -reg [15:0] mcf_opcode_reg = 0, mcf_opcode_next; -reg [MCF_PARAMS_SIZE*8-1:0] mcf_params_reg = 0, mcf_params_next; -reg [ID_WIDTH-1:0] mcf_id_reg = 0, mcf_id_next; -reg [DEST_WIDTH-1:0] mcf_dest_reg = 0, mcf_dest_next; -reg [USER_WIDTH-1:0] mcf_user_reg = 0, mcf_user_next; - -reg stat_rx_mcf_reg = 1'b0, stat_rx_mcf_next; - -assign s_axis_tready = s_axis_tready_reg; - -assign mcf_valid = mcf_valid_reg; -assign mcf_eth_dst = mcf_eth_dst_reg; -assign mcf_eth_src = mcf_eth_src_reg; -assign mcf_eth_type = mcf_eth_type_reg; -assign mcf_opcode = mcf_opcode_reg; -assign mcf_params = mcf_params_reg; -assign mcf_id = mcf_id_reg; -assign mcf_dest = mcf_dest_reg; -assign mcf_user = mcf_user_reg; - -assign stat_rx_mcf = stat_rx_mcf_reg; - -wire mcf_eth_dst_mcast_match = mcf_eth_dst_next == cfg_mcf_rx_eth_dst_mcast; -wire mcf_eth_dst_ucast_match = mcf_eth_dst_next == cfg_mcf_rx_eth_dst_ucast; -wire mcf_eth_src_match = mcf_eth_src_next == cfg_mcf_rx_eth_src; -wire mcf_eth_type_match = mcf_eth_type_next == cfg_mcf_rx_eth_type; -wire mcf_opcode_lfc_match = mcf_opcode_next == cfg_mcf_rx_opcode_lfc; -wire mcf_opcode_pfc_match = mcf_opcode_next == cfg_mcf_rx_opcode_pfc; - -wire mcf_eth_dst_match = ((mcf_eth_dst_mcast_match && cfg_mcf_rx_check_eth_dst_mcast) || - (mcf_eth_dst_ucast_match && cfg_mcf_rx_check_eth_dst_ucast) || - (!cfg_mcf_rx_check_eth_dst_mcast && !cfg_mcf_rx_check_eth_dst_ucast)); - -wire mcf_opcode_match = ((mcf_opcode_lfc_match && cfg_mcf_rx_check_opcode_lfc) || - (mcf_opcode_pfc_match && cfg_mcf_rx_check_opcode_pfc) || - (!cfg_mcf_rx_check_opcode_lfc && !cfg_mcf_rx_check_opcode_pfc)); - -wire mcf_match = (mcf_eth_dst_match && - (mcf_eth_src_match || !cfg_mcf_rx_check_eth_src) && - mcf_eth_type_match && mcf_opcode_match); - -integer k; - -always @* begin - read_mcf_next = read_mcf_reg; - mcf_frame_next = mcf_frame_reg; - ptr_next = ptr_reg; - - // pass through data - m_axis_tdata_int = s_axis_tdata; - m_axis_tkeep_int = s_axis_tkeep; - m_axis_tvalid_int = s_axis_tvalid; - m_axis_tlast_int = s_axis_tlast; - m_axis_tid_int = s_axis_tid; - m_axis_tdest_int = s_axis_tdest; - m_axis_tuser_int = s_axis_tuser; - - s_axis_tready_next = m_axis_tready_int_early || !USE_READY; - - mcf_valid_next = 1'b0; - mcf_eth_dst_next = mcf_eth_dst_reg; - mcf_eth_src_next = mcf_eth_src_reg; - mcf_eth_type_next = mcf_eth_type_reg; - mcf_opcode_next = mcf_opcode_reg; - mcf_params_next = mcf_params_reg; - mcf_id_next = mcf_id_reg; - mcf_dest_next = mcf_dest_reg; - mcf_user_next = mcf_user_reg; - - stat_rx_mcf_next = 1'b0; - - if ((s_axis_tready || !USE_READY) && s_axis_tvalid) begin - if (read_mcf_reg) begin - ptr_next = ptr_reg + 1; - - mcf_id_next = s_axis_tid; - mcf_dest_next = s_axis_tdest; - mcf_user_next = s_axis_tuser; - - `define _HEADER_FIELD_(offset, field) \ - if (ptr_reg == offset/BYTE_LANES) begin \ - field = s_axis_tdata[(offset%BYTE_LANES)*8 +: 8]; \ - end - - `_HEADER_FIELD_(0, mcf_eth_dst_next[5*8 +: 8]) - `_HEADER_FIELD_(1, mcf_eth_dst_next[4*8 +: 8]) - `_HEADER_FIELD_(2, mcf_eth_dst_next[3*8 +: 8]) - `_HEADER_FIELD_(3, mcf_eth_dst_next[2*8 +: 8]) - `_HEADER_FIELD_(4, mcf_eth_dst_next[1*8 +: 8]) - `_HEADER_FIELD_(5, mcf_eth_dst_next[0*8 +: 8]) - `_HEADER_FIELD_(6, mcf_eth_src_next[5*8 +: 8]) - `_HEADER_FIELD_(7, mcf_eth_src_next[4*8 +: 8]) - `_HEADER_FIELD_(8, mcf_eth_src_next[3*8 +: 8]) - `_HEADER_FIELD_(9, mcf_eth_src_next[2*8 +: 8]) - `_HEADER_FIELD_(10, mcf_eth_src_next[1*8 +: 8]) - `_HEADER_FIELD_(11, mcf_eth_src_next[0*8 +: 8]) - `_HEADER_FIELD_(12, mcf_eth_type_next[1*8 +: 8]) - `_HEADER_FIELD_(13, mcf_eth_type_next[0*8 +: 8]) - `_HEADER_FIELD_(14, mcf_opcode_next[1*8 +: 8]) - `_HEADER_FIELD_(15, mcf_opcode_next[0*8 +: 8]) - - if (ptr_reg == 0/BYTE_LANES) begin - // ensure params field gets cleared - mcf_params_next = 0; - end - - for (k = 0; k < MCF_PARAMS_SIZE; k = k + 1) begin - if (ptr_reg == (16+k)/BYTE_LANES) begin - mcf_params_next[k*8 +: 8] = s_axis_tdata[((16+k)%BYTE_LANES)*8 +: 8]; - end - end - - if (ptr_reg == 15/BYTE_LANES && (!KEEP_ENABLE || s_axis_tkeep[13%BYTE_LANES])) begin - // record match at end of opcode field - mcf_frame_next = mcf_match && cfg_mcf_rx_enable; - end - - if (ptr_reg == (HDR_SIZE-1)/BYTE_LANES) begin - read_mcf_next = 1'b0; - end - - `undef _HEADER_FIELD_ - end - - if (s_axis_tlast) begin - if (s_axis_tuser[0]) begin - // frame marked invalid - end else if (mcf_frame_next) begin - if (!cfg_mcf_rx_forward) begin - // mark frame invalid - m_axis_tuser_int[0] = 1'b1; - end - // transfer out MAC control frame - mcf_valid_next = 1'b1; - stat_rx_mcf_next = 1'b1; - end - - read_mcf_next = 1'b1; - mcf_frame_next = 1'b0; - ptr_next = 0; - end - end -end - -always @(posedge clk) begin - read_mcf_reg <= read_mcf_next; - mcf_frame_reg <= mcf_frame_next; - ptr_reg <= ptr_next; - - s_axis_tready_reg <= s_axis_tready_next; - - mcf_valid_reg <= mcf_valid_next; - mcf_eth_dst_reg <= mcf_eth_dst_next; - mcf_eth_src_reg <= mcf_eth_src_next; - mcf_eth_type_reg <= mcf_eth_type_next; - mcf_opcode_reg <= mcf_opcode_next; - mcf_params_reg <= mcf_params_next; - mcf_id_reg <= mcf_id_next; - mcf_dest_reg <= mcf_dest_next; - mcf_user_reg <= mcf_user_next; - - stat_rx_mcf_reg <= stat_rx_mcf_next; - - if (rst) begin - read_mcf_reg <= 1'b1; - mcf_frame_reg <= 1'b0; - ptr_reg <= 0; - s_axis_tready_reg <= 1'b0; - mcf_valid_reg <= 1'b0; - stat_rx_mcf_reg <= 1'b0; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; -reg temp_m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; -assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; -assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign m_axis_tready_int_early = m_axis_tready || !USE_READY || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int)); - -always @* begin - // transfer sink ready state to source - m_axis_tvalid_next = m_axis_tvalid_reg; - temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (m_axis_tready_int_reg) begin - // input is ready - if (m_axis_tready || !USE_READY || !m_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (m_axis_tready || !USE_READY) begin - // input is not ready, but output is ready - m_axis_tvalid_next = temp_m_axis_tvalid_reg; - temp_m_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tready_int_reg <= m_axis_tready_int_early; - temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; - - // datapath - if (store_axis_int_to_output) begin - m_axis_tdata_reg <= m_axis_tdata_int; - m_axis_tkeep_reg <= m_axis_tkeep_int; - m_axis_tlast_reg <= m_axis_tlast_int; - m_axis_tid_reg <= m_axis_tid_int; - m_axis_tdest_reg <= m_axis_tdest_int; - m_axis_tuser_reg <= m_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - m_axis_tdata_reg <= temp_m_axis_tdata_reg; - m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; - m_axis_tlast_reg <= temp_m_axis_tlast_reg; - m_axis_tid_reg <= temp_m_axis_tid_reg; - m_axis_tdest_reg <= temp_m_axis_tdest_reg; - m_axis_tuser_reg <= temp_m_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_m_axis_tdata_reg <= m_axis_tdata_int; - temp_m_axis_tkeep_reg <= m_axis_tkeep_int; - temp_m_axis_tlast_reg <= m_axis_tlast_int; - temp_m_axis_tid_reg <= m_axis_tid_int; - temp_m_axis_tdest_reg <= m_axis_tdest_int; - temp_m_axis_tuser_reg <= m_axis_tuser_int; - end - - if (rst) begin - m_axis_tvalid_reg <= 1'b0; - m_axis_tready_int_reg <= 1'b0; - temp_m_axis_tvalid_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mac_ctrl_tx.sv b/src/rvvi/mac_ctrl_tx.sv deleted file mode 100644 index 3d321fd64..000000000 --- a/src/rvvi/mac_ctrl_tx.sv +++ /dev/null @@ -1,420 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * MAC control transmit - */ -module mac_ctrl_tx # -( - parameter DATA_WIDTH = 8, - parameter KEEP_ENABLE = DATA_WIDTH>8, - parameter KEEP_WIDTH = DATA_WIDTH/8, - parameter ID_ENABLE = 0, - parameter ID_WIDTH = 8, - parameter DEST_ENABLE = 0, - parameter DEST_WIDTH = 8, - parameter USER_ENABLE = 1, - parameter USER_WIDTH = 1, - parameter MCF_PARAMS_SIZE = 18 -) -( - input wire clk, - input wire rst, - - /* - * AXI stream input - */ - input wire [DATA_WIDTH-1:0] s_axis_tdata, - input wire [KEEP_WIDTH-1:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire [ID_WIDTH-1:0] s_axis_tid, - input wire [DEST_WIDTH-1:0] s_axis_tdest, - input wire [USER_WIDTH-1:0] s_axis_tuser, - - /* - * AXI stream output - */ - output wire [DATA_WIDTH-1:0] m_axis_tdata, - output wire [KEEP_WIDTH-1:0] m_axis_tkeep, - output wire m_axis_tvalid, - input wire m_axis_tready, - output wire m_axis_tlast, - output wire [ID_WIDTH-1:0] m_axis_tid, - output wire [DEST_WIDTH-1:0] m_axis_tdest, - output wire [USER_WIDTH-1:0] m_axis_tuser, - - /* - * MAC control frame interface - */ - input wire mcf_valid, - output wire mcf_ready, - input wire [47:0] mcf_eth_dst, - input wire [47:0] mcf_eth_src, - input wire [15:0] mcf_eth_type, - input wire [15:0] mcf_opcode, - input wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - input wire [ID_WIDTH-1:0] mcf_id, - input wire [DEST_WIDTH-1:0] mcf_dest, - input wire [USER_WIDTH-1:0] mcf_user, - - /* - * Pause interface - */ - input wire tx_pause_req, - output wire tx_pause_ack, - - /* - * Status - */ - output wire stat_tx_mcf -); - -parameter BYTE_LANES = KEEP_ENABLE ? KEEP_WIDTH : 1; - -parameter HDR_SIZE = 60; - -parameter CYCLE_COUNT = (HDR_SIZE+BYTE_LANES-1)/BYTE_LANES; - -parameter PTR_WIDTH = $clog2(CYCLE_COUNT); - -parameter OFFSET = HDR_SIZE % BYTE_LANES; - -// check configuration -initial begin - if (BYTE_LANES * 8 != DATA_WIDTH) begin - $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); - $finish; - end - - if (MCF_PARAMS_SIZE > 44) begin - $error("Error: Maximum MCF_PARAMS_SIZE is 44 bytes (instance %m)"); - $finish; - end -end - -/* - -MAC control frame - - Field Length - Destination MAC address 6 octets [01:80:C2:00:00:01] - Source MAC address 6 octets - Ethertype 2 octets [0x8808] - Opcode 2 octets - Parameters 0-44 octets - -This module manages the transmission of MAC control frames. Control frames -are accepted in parallel, serialized, and merged at a higher priority with -data traffic. - -*/ - -reg send_data_reg = 1'b0, send_data_next; -reg send_mcf_reg = 1'b0, send_mcf_next; -reg [PTR_WIDTH-1:0] ptr_reg = 0, ptr_next; - -reg s_axis_tready_reg = 1'b0, s_axis_tready_next; -reg mcf_ready_reg = 1'b0, mcf_ready_next; -reg tx_pause_ack_reg = 1'b0, tx_pause_ack_next; -reg stat_tx_mcf_reg = 1'b0, stat_tx_mcf_next; - -// internal datapath -reg [DATA_WIDTH-1:0] m_axis_tdata_int; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_int; -reg m_axis_tvalid_int; -reg m_axis_tready_int_reg = 1'b0; -reg m_axis_tlast_int; -reg [ID_WIDTH-1:0] m_axis_tid_int; -reg [DEST_WIDTH-1:0] m_axis_tdest_int; -reg [USER_WIDTH-1:0] m_axis_tuser_int; -wire m_axis_tready_int_early; - -assign s_axis_tready = s_axis_tready_reg; -assign mcf_ready = mcf_ready_reg; -assign tx_pause_ack = tx_pause_ack_reg; -assign stat_tx_mcf = stat_tx_mcf_reg; - -integer k; - -always @* begin - send_data_next = send_data_reg; - send_mcf_next = send_mcf_reg; - ptr_next = ptr_reg; - - s_axis_tready_next = 1'b0; - mcf_ready_next = 1'b0; - tx_pause_ack_next = tx_pause_ack_reg; - stat_tx_mcf_next = 1'b0; - - m_axis_tdata_int = 0; - m_axis_tkeep_int = 0; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = 1'b0; - m_axis_tid_int = 0; - m_axis_tdest_int = 0; - m_axis_tuser_int = 0; - - if (!send_data_reg && !send_mcf_reg) begin - m_axis_tdata_int = s_axis_tdata; - m_axis_tkeep_int = s_axis_tkeep; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = s_axis_tlast; - m_axis_tid_int = s_axis_tid; - m_axis_tdest_int = s_axis_tdest; - m_axis_tuser_int = s_axis_tuser; - s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; - tx_pause_ack_next = tx_pause_req; - if (s_axis_tvalid && s_axis_tready) begin - s_axis_tready_next = m_axis_tready_int_early; - tx_pause_ack_next = 1'b0; - m_axis_tvalid_int = 1'b1; - if (s_axis_tlast) begin - s_axis_tready_next = m_axis_tready_int_early && !mcf_valid && !mcf_ready; - send_data_next = 1'b0; - end else begin - send_data_next = 1'b1; - end - end else if (mcf_valid) begin - s_axis_tready_next = 1'b0; - ptr_next = 0; - send_mcf_next = 1'b1; - mcf_ready_next = (CYCLE_COUNT == 1) && m_axis_tready_int_early; - end - end - - if (send_data_reg) begin - m_axis_tdata_int = s_axis_tdata; - m_axis_tkeep_int = s_axis_tkeep; - m_axis_tvalid_int = 1'b0; - m_axis_tlast_int = s_axis_tlast; - m_axis_tid_int = s_axis_tid; - m_axis_tdest_int = s_axis_tdest; - m_axis_tuser_int = s_axis_tuser; - s_axis_tready_next = m_axis_tready_int_early; - if (s_axis_tvalid && s_axis_tready) begin - m_axis_tvalid_int = 1'b1; - if (s_axis_tlast) begin - s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; - send_data_next = 1'b0; - if (mcf_valid) begin - s_axis_tready_next = 1'b0; - ptr_next = 0; - send_mcf_next = 1'b1; - mcf_ready_next = (CYCLE_COUNT == 1) && m_axis_tready_int_early; - end - end else begin - send_data_next = 1'b1; - end - end - end - - if (send_mcf_reg) begin - mcf_ready_next = (CYCLE_COUNT == 1 || ptr_reg == CYCLE_COUNT-1) && m_axis_tready_int_early; - if (m_axis_tready_int_reg) begin - ptr_next = ptr_reg + 1; - - m_axis_tvalid_int = 1'b1; - m_axis_tid_int = mcf_id; - m_axis_tdest_int = mcf_dest; - m_axis_tuser_int = mcf_user; - - `define _HEADER_FIELD_(offset, field) \ - if (ptr_reg == offset/BYTE_LANES) begin \ - m_axis_tdata_int[(offset%BYTE_LANES)*8 +: 8] = field; \ - m_axis_tkeep_int[offset%BYTE_LANES] = 1'b1; \ - end - - `_HEADER_FIELD_(0, mcf_eth_dst[5*8 +: 8]) - `_HEADER_FIELD_(1, mcf_eth_dst[4*8 +: 8]) - `_HEADER_FIELD_(2, mcf_eth_dst[3*8 +: 8]) - `_HEADER_FIELD_(3, mcf_eth_dst[2*8 +: 8]) - `_HEADER_FIELD_(4, mcf_eth_dst[1*8 +: 8]) - `_HEADER_FIELD_(5, mcf_eth_dst[0*8 +: 8]) - `_HEADER_FIELD_(6, mcf_eth_src[5*8 +: 8]) - `_HEADER_FIELD_(7, mcf_eth_src[4*8 +: 8]) - `_HEADER_FIELD_(8, mcf_eth_src[3*8 +: 8]) - `_HEADER_FIELD_(9, mcf_eth_src[2*8 +: 8]) - `_HEADER_FIELD_(10, mcf_eth_src[1*8 +: 8]) - `_HEADER_FIELD_(11, mcf_eth_src[0*8 +: 8]) - `_HEADER_FIELD_(12, mcf_eth_type[1*8 +: 8]) - `_HEADER_FIELD_(13, mcf_eth_type[0*8 +: 8]) - `_HEADER_FIELD_(14, mcf_opcode[1*8 +: 8]) - `_HEADER_FIELD_(15, mcf_opcode[0*8 +: 8]) - - for (k = 0; k < HDR_SIZE-16; k = k + 1) begin - if (ptr_reg == (16+k)/BYTE_LANES) begin - if (k < MCF_PARAMS_SIZE) begin - m_axis_tdata_int[((16+k)%BYTE_LANES)*8 +: 8] = mcf_params[k*8 +: 8]; - end else begin - m_axis_tdata_int[((16+k)%BYTE_LANES)*8 +: 8] = 0; - end - m_axis_tkeep_int[(16+k)%BYTE_LANES] = 1'b1; - end - end - - if (ptr_reg == (HDR_SIZE-1)/BYTE_LANES) begin - s_axis_tready_next = m_axis_tready_int_early && !tx_pause_req; - mcf_ready_next = 1'b0; - m_axis_tlast_int = 1'b1; - send_mcf_next = 1'b0; - stat_tx_mcf_next = 1'b1; - end else begin - mcf_ready_next = (ptr_next == CYCLE_COUNT-1) && m_axis_tready_int_early; - end - - `undef _HEADER_FIELD_ - end - end -end - -always @(posedge clk) begin - send_data_reg <= send_data_next; - send_mcf_reg <= send_mcf_next; - ptr_reg <= ptr_next; - - s_axis_tready_reg <= s_axis_tready_next; - mcf_ready_reg <= mcf_ready_next; - tx_pause_ack_reg <= tx_pause_ack_next; - stat_tx_mcf_reg <= stat_tx_mcf_next; - - if (rst) begin - send_data_reg <= 1'b0; - send_mcf_reg <= 1'b0; - ptr_reg <= 0; - s_axis_tready_reg <= 1'b0; - mcf_ready_reg <= 1'b0; - tx_pause_ack_reg <= 1'b0; - stat_tx_mcf_reg <= 1'b0; - end -end - -// output datapath logic -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next; -reg m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}}; -reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}; -reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next; -reg temp_m_axis_tlast_reg = 1'b0; -reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}}; -reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}}; -reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}}; - -// datapath control -reg store_axis_int_to_output; -reg store_axis_int_to_temp; -reg store_axis_temp_to_output; - -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}}; -assign m_axis_tvalid = m_axis_tvalid_reg; -assign m_axis_tlast = m_axis_tlast_reg; -assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}}; -assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}}; -assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}}; - -// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input) -assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int)); - -always @* begin - // transfer sink ready state to source - m_axis_tvalid_next = m_axis_tvalid_reg; - temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg; - - store_axis_int_to_output = 1'b0; - store_axis_int_to_temp = 1'b0; - store_axis_temp_to_output = 1'b0; - - if (m_axis_tready_int_reg) begin - // input is ready - if (m_axis_tready || !m_axis_tvalid_reg) begin - // output is ready or currently not valid, transfer data to output - m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_output = 1'b1; - end else begin - // output is not ready, store input in temp - temp_m_axis_tvalid_next = m_axis_tvalid_int; - store_axis_int_to_temp = 1'b1; - end - end else if (m_axis_tready) begin - // input is not ready, but output is ready - m_axis_tvalid_next = temp_m_axis_tvalid_reg; - temp_m_axis_tvalid_next = 1'b0; - store_axis_temp_to_output = 1'b1; - end -end - -always @(posedge clk) begin - m_axis_tvalid_reg <= m_axis_tvalid_next; - m_axis_tready_int_reg <= m_axis_tready_int_early; - temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next; - - // datapath - if (store_axis_int_to_output) begin - m_axis_tdata_reg <= m_axis_tdata_int; - m_axis_tkeep_reg <= m_axis_tkeep_int; - m_axis_tlast_reg <= m_axis_tlast_int; - m_axis_tid_reg <= m_axis_tid_int; - m_axis_tdest_reg <= m_axis_tdest_int; - m_axis_tuser_reg <= m_axis_tuser_int; - end else if (store_axis_temp_to_output) begin - m_axis_tdata_reg <= temp_m_axis_tdata_reg; - m_axis_tkeep_reg <= temp_m_axis_tkeep_reg; - m_axis_tlast_reg <= temp_m_axis_tlast_reg; - m_axis_tid_reg <= temp_m_axis_tid_reg; - m_axis_tdest_reg <= temp_m_axis_tdest_reg; - m_axis_tuser_reg <= temp_m_axis_tuser_reg; - end - - if (store_axis_int_to_temp) begin - temp_m_axis_tdata_reg <= m_axis_tdata_int; - temp_m_axis_tkeep_reg <= m_axis_tkeep_int; - temp_m_axis_tlast_reg <= m_axis_tlast_int; - temp_m_axis_tid_reg <= m_axis_tid_int; - temp_m_axis_tdest_reg <= m_axis_tdest_int; - temp_m_axis_tuser_reg <= m_axis_tuser_int; - end - - if (rst) begin - m_axis_tvalid_reg <= 1'b0; - m_axis_tready_int_reg <= 1'b0; - temp_m_axis_tvalid_reg <= 1'b0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mac_pause_ctrl_rx.sv b/src/rvvi/mac_pause_ctrl_rx.sv deleted file mode 100644 index e95c07bf9..000000000 --- a/src/rvvi/mac_pause_ctrl_rx.sv +++ /dev/null @@ -1,220 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * PFC and pause frame receive handling - */ -module mac_pause_ctrl_rx # -( - parameter MCF_PARAMS_SIZE = 18, - parameter PFC_ENABLE = 1 -) -( - input wire clk, - input wire rst, - - /* - * MAC control frame interface - */ - input wire mcf_valid, - input wire [47:0] mcf_eth_dst, - input wire [47:0] mcf_eth_src, - input wire [15:0] mcf_eth_type, - input wire [15:0] mcf_opcode, - input wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - - /* - * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) - */ - input wire rx_lfc_en, - output wire rx_lfc_req, - input wire rx_lfc_ack, - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) - */ - input wire [7:0] rx_pfc_en, - output wire [7:0] rx_pfc_req, - input wire [7:0] rx_pfc_ack, - - /* - * Configuration - */ - input wire [15:0] cfg_rx_lfc_opcode, - input wire cfg_rx_lfc_en, - input wire [15:0] cfg_rx_pfc_opcode, - input wire cfg_rx_pfc_en, - input wire [9:0] cfg_quanta_step, - input wire cfg_quanta_clk_en, - - /* - * Status - */ - output wire stat_rx_lfc_pkt, - output wire stat_rx_lfc_xon, - output wire stat_rx_lfc_xoff, - output wire stat_rx_lfc_paused, - output wire stat_rx_pfc_pkt, - output wire [7:0] stat_rx_pfc_xon, - output wire [7:0] stat_rx_pfc_xoff, - output wire [7:0] stat_rx_pfc_paused -); - -localparam QFB = 8; - -// check configuration -initial begin - if (MCF_PARAMS_SIZE < (PFC_ENABLE ? 18 : 2)) begin - $error("Error: MCF_PARAMS_SIZE too small for requested configuration (instance %m)"); - $finish; - end -end - -reg lfc_req_reg = 1'b0, lfc_req_next; -reg [7:0] pfc_req_reg = 8'd0, pfc_req_next; - -reg [16+QFB-1:0] lfc_quanta_reg = 0, lfc_quanta_next; -reg [16+QFB-1:0] pfc_quanta_reg[0:7], pfc_quanta_next[0:7]; - -reg stat_rx_lfc_pkt_reg = 1'b0, stat_rx_lfc_pkt_next; -reg stat_rx_lfc_xon_reg = 1'b0, stat_rx_lfc_xon_next; -reg stat_rx_lfc_xoff_reg = 1'b0, stat_rx_lfc_xoff_next; -reg stat_rx_pfc_pkt_reg = 1'b0, stat_rx_pfc_pkt_next; -reg [7:0] stat_rx_pfc_xon_reg = 0, stat_rx_pfc_xon_next; -reg [7:0] stat_rx_pfc_xoff_reg = 0, stat_rx_pfc_xoff_next; - -assign rx_lfc_req = lfc_req_reg; -assign rx_pfc_req = pfc_req_reg; - -assign stat_rx_lfc_pkt = stat_rx_lfc_pkt_reg; -assign stat_rx_lfc_xon = stat_rx_lfc_xon_reg; -assign stat_rx_lfc_xoff = stat_rx_lfc_xoff_reg; -assign stat_rx_lfc_paused = lfc_req_reg; -assign stat_rx_pfc_pkt = stat_rx_pfc_pkt_reg; -assign stat_rx_pfc_xon = stat_rx_pfc_xon_reg; -assign stat_rx_pfc_xoff = stat_rx_pfc_xoff_reg; -assign stat_rx_pfc_paused = pfc_req_reg; - -integer k; - -initial begin - for (k = 0; k < 8; k = k + 1) begin - pfc_quanta_reg[k] = 0; - end -end - -always @* begin - stat_rx_lfc_pkt_next = 1'b0; - stat_rx_lfc_xon_next = 1'b0; - stat_rx_lfc_xoff_next = 1'b0; - stat_rx_pfc_pkt_next = 1'b0; - stat_rx_pfc_xon_next = 0; - stat_rx_pfc_xoff_next = 0; - - if (cfg_quanta_clk_en && rx_lfc_ack) begin - if (lfc_quanta_reg > cfg_quanta_step) begin - lfc_quanta_next = lfc_quanta_reg - cfg_quanta_step; - end else begin - lfc_quanta_next = 0; - end - end else begin - lfc_quanta_next = lfc_quanta_reg; - end - - lfc_req_next = (lfc_quanta_reg != 0) && rx_lfc_en && cfg_rx_lfc_en; - - for (k = 0; k < 8; k = k + 1) begin - if (cfg_quanta_clk_en && rx_pfc_ack[k]) begin - if (pfc_quanta_reg[k] > cfg_quanta_step) begin - pfc_quanta_next[k] = pfc_quanta_reg[k] - cfg_quanta_step; - end else begin - pfc_quanta_next[k] = 0; - end - end else begin - pfc_quanta_next[k] = pfc_quanta_reg[k]; - end - - pfc_req_next[k] = (pfc_quanta_reg[k] != 0) && rx_pfc_en[k] && cfg_rx_pfc_en; - end - - if (mcf_valid) begin - if (mcf_opcode == cfg_rx_lfc_opcode && cfg_rx_lfc_en) begin - stat_rx_lfc_pkt_next = 1'b1; - stat_rx_lfc_xon_next = {mcf_params[7:0], mcf_params[15:8]} == 0; - stat_rx_lfc_xoff_next = {mcf_params[7:0], mcf_params[15:8]} != 0; - lfc_quanta_next = {mcf_params[7:0], mcf_params[15:8], {QFB{1'b0}}}; - end else if (PFC_ENABLE && mcf_opcode == cfg_rx_pfc_opcode && cfg_rx_pfc_en) begin - stat_rx_pfc_pkt_next = 1'b1; - for (k = 0; k < 8; k = k + 1) begin - if (mcf_params[k+8]) begin - stat_rx_pfc_xon_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8]} == 0; - stat_rx_pfc_xoff_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8]} != 0; - pfc_quanta_next[k] = {mcf_params[16+(k*16)+0 +: 8], mcf_params[16+(k*16)+8 +: 8], {QFB{1'b0}}}; - end - end - end - end -end - -always @(posedge clk) begin - lfc_req_reg <= lfc_req_next; - pfc_req_reg <= pfc_req_next; - - lfc_quanta_reg <= lfc_quanta_next; - for (k = 0; k < 8; k = k + 1) begin - pfc_quanta_reg[k] <= pfc_quanta_next[k]; - end - - stat_rx_lfc_pkt_reg <= stat_rx_lfc_pkt_next; - stat_rx_lfc_xon_reg <= stat_rx_lfc_xon_next; - stat_rx_lfc_xoff_reg <= stat_rx_lfc_xoff_next; - stat_rx_pfc_pkt_reg <= stat_rx_pfc_pkt_next; - stat_rx_pfc_xon_reg <= stat_rx_pfc_xon_next; - stat_rx_pfc_xoff_reg <= stat_rx_pfc_xoff_next; - - if (rst) begin - lfc_req_reg <= 1'b0; - pfc_req_reg <= 8'd0; - lfc_quanta_reg <= 0; - for (k = 0; k < 8; k = k + 1) begin - pfc_quanta_reg[k] <= 0; - end - - stat_rx_lfc_pkt_reg <= 1'b0; - stat_rx_lfc_xon_reg <= 1'b0; - stat_rx_lfc_xoff_reg <= 1'b0; - stat_rx_pfc_pkt_reg <= 1'b0; - stat_rx_pfc_xon_reg <= 0; - stat_rx_pfc_xoff_reg <= 0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mac_pause_ctrl_tx.sv b/src/rvvi/mac_pause_ctrl_tx.sv deleted file mode 100644 index 20566d888..000000000 --- a/src/rvvi/mac_pause_ctrl_tx.sv +++ /dev/null @@ -1,312 +0,0 @@ -/* - -Copyright (c) 2023 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * PFC and pause frame transmit handling - */ -module mac_pause_ctrl_tx # -( - parameter MCF_PARAMS_SIZE = 18, - parameter PFC_ENABLE = 1 -) -( - input wire clk, - input wire rst, - - /* - * MAC control frame interface - */ - output wire mcf_valid, - input wire mcf_ready, - output wire [47:0] mcf_eth_dst, - output wire [47:0] mcf_eth_src, - output wire [15:0] mcf_eth_type, - output wire [15:0] mcf_opcode, - output wire [MCF_PARAMS_SIZE*8-1:0] mcf_params, - - /* - * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) - */ - input wire tx_lfc_req, - input wire tx_lfc_resend, - - /* - * Priority Flow Control (PFC) (IEEE 802.3 annex 31D) - */ - input wire [7:0] tx_pfc_req, - input wire tx_pfc_resend, - - /* - * Configuration - */ - input wire [47:0] cfg_tx_lfc_eth_dst, - input wire [47:0] cfg_tx_lfc_eth_src, - input wire [15:0] cfg_tx_lfc_eth_type, - input wire [15:0] cfg_tx_lfc_opcode, - input wire cfg_tx_lfc_en, - input wire [15:0] cfg_tx_lfc_quanta, - input wire [15:0] cfg_tx_lfc_refresh, - input wire [47:0] cfg_tx_pfc_eth_dst, - input wire [47:0] cfg_tx_pfc_eth_src, - input wire [15:0] cfg_tx_pfc_eth_type, - input wire [15:0] cfg_tx_pfc_opcode, - input wire cfg_tx_pfc_en, - input wire [8*16-1:0] cfg_tx_pfc_quanta, - input wire [8*16-1:0] cfg_tx_pfc_refresh, - input wire [9:0] cfg_quanta_step, - input wire cfg_quanta_clk_en, - - /* - * Status - */ - output wire stat_tx_lfc_pkt, - output wire stat_tx_lfc_xon, - output wire stat_tx_lfc_xoff, - output wire stat_tx_lfc_paused, - output wire stat_tx_pfc_pkt, - output wire [7:0] stat_tx_pfc_xon, - output wire [7:0] stat_tx_pfc_xoff, - output wire [7:0] stat_tx_pfc_paused -); - -localparam QFB = 8; - -// check configuration -initial begin - if (MCF_PARAMS_SIZE < (PFC_ENABLE ? 18 : 2)) begin - $error("Error: MCF_PARAMS_SIZE too small for requested configuration (instance %m)"); - $finish; - end -end - -reg lfc_req_reg = 1'b0, lfc_req_next; -reg lfc_act_reg = 1'b0, lfc_act_next; -reg lfc_send_reg = 1'b0, lfc_send_next; -reg [7:0] pfc_req_reg = 8'd0, pfc_req_next; -reg [7:0] pfc_act_reg = 8'd0, pfc_act_next; -reg [7:0] pfc_en_reg = 8'd0, pfc_en_next; -reg pfc_send_reg = 1'b0, pfc_send_next; - -reg [16+QFB-1:0] lfc_refresh_reg = 0, lfc_refresh_next; -reg [16+QFB-1:0] pfc_refresh_reg[0:7], pfc_refresh_next[0:7]; - -reg stat_tx_lfc_pkt_reg = 1'b0, stat_tx_lfc_pkt_next; -reg stat_tx_lfc_xon_reg = 1'b0, stat_tx_lfc_xon_next; -reg stat_tx_lfc_xoff_reg = 1'b0, stat_tx_lfc_xoff_next; -reg stat_tx_pfc_pkt_reg = 1'b0, stat_tx_pfc_pkt_next; -reg [7:0] stat_tx_pfc_xon_reg = 0, stat_tx_pfc_xon_next; -reg [7:0] stat_tx_pfc_xoff_reg = 0, stat_tx_pfc_xoff_next; - -// MAC control interface -reg mcf_pfc_sel_reg = PFC_ENABLE != 0, mcf_pfc_sel_next; -reg mcf_valid_reg = 1'b0, mcf_valid_next; - -wire [2*8-1:0] mcf_lfc_params; -assign mcf_lfc_params[16*0 +: 16] = lfc_req_reg ? {cfg_tx_lfc_quanta[0 +: 8], cfg_tx_lfc_quanta[8 +: 8]} : 0; - -wire [18*8-1:0] mcf_pfc_params; -assign mcf_pfc_params[16*0 +: 16] = {pfc_en_reg, 8'd0}; -assign mcf_pfc_params[16*1 +: 16] = pfc_req_reg[0] ? {cfg_tx_pfc_quanta[16*0+0 +: 8], cfg_tx_pfc_quanta[16*0+8 +: 8]} : 0; -assign mcf_pfc_params[16*2 +: 16] = pfc_req_reg[1] ? {cfg_tx_pfc_quanta[16*1+0 +: 8], cfg_tx_pfc_quanta[16*1+8 +: 8]} : 0; -assign mcf_pfc_params[16*3 +: 16] = pfc_req_reg[2] ? {cfg_tx_pfc_quanta[16*2+0 +: 8], cfg_tx_pfc_quanta[16*2+8 +: 8]} : 0; -assign mcf_pfc_params[16*4 +: 16] = pfc_req_reg[3] ? {cfg_tx_pfc_quanta[16*3+0 +: 8], cfg_tx_pfc_quanta[16*3+8 +: 8]} : 0; -assign mcf_pfc_params[16*5 +: 16] = pfc_req_reg[4] ? {cfg_tx_pfc_quanta[16*4+0 +: 8], cfg_tx_pfc_quanta[16*4+8 +: 8]} : 0; -assign mcf_pfc_params[16*6 +: 16] = pfc_req_reg[5] ? {cfg_tx_pfc_quanta[16*5+0 +: 8], cfg_tx_pfc_quanta[16*5+8 +: 8]} : 0; -assign mcf_pfc_params[16*7 +: 16] = pfc_req_reg[6] ? {cfg_tx_pfc_quanta[16*6+0 +: 8], cfg_tx_pfc_quanta[16*6+8 +: 8]} : 0; -assign mcf_pfc_params[16*8 +: 16] = pfc_req_reg[7] ? {cfg_tx_pfc_quanta[16*7+0 +: 8], cfg_tx_pfc_quanta[16*7+8 +: 8]} : 0; - -assign mcf_valid = mcf_valid_reg; -assign mcf_eth_dst = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_dst : cfg_tx_lfc_eth_dst; -assign mcf_eth_src = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_src : cfg_tx_lfc_eth_src; -assign mcf_eth_type = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_eth_type : cfg_tx_lfc_eth_type; -assign mcf_opcode = (PFC_ENABLE && mcf_pfc_sel_reg) ? cfg_tx_pfc_opcode : cfg_tx_lfc_opcode; -assign mcf_params = (PFC_ENABLE && mcf_pfc_sel_reg) ? mcf_pfc_params : mcf_lfc_params; - -assign stat_tx_lfc_pkt = stat_tx_lfc_pkt_reg; -assign stat_tx_lfc_xon = stat_tx_lfc_xon_reg; -assign stat_tx_lfc_xoff = stat_tx_lfc_xoff_reg; -assign stat_tx_lfc_paused = lfc_req_reg; -assign stat_tx_pfc_pkt = stat_tx_pfc_pkt_reg; -assign stat_tx_pfc_xon = stat_tx_pfc_xon_reg; -assign stat_tx_pfc_xoff = stat_tx_pfc_xoff_reg; -assign stat_tx_pfc_paused = pfc_req_reg; - -integer k; - -initial begin - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_reg[k] = 0; - end -end - -always @* begin - lfc_req_next = lfc_req_reg; - lfc_act_next = lfc_act_reg; - lfc_send_next = lfc_send_reg | tx_lfc_resend; - pfc_req_next = pfc_req_reg; - pfc_act_next = pfc_act_reg; - pfc_en_next = pfc_en_reg; - pfc_send_next = pfc_send_reg | tx_pfc_resend; - - mcf_pfc_sel_next = mcf_pfc_sel_reg; - mcf_valid_next = mcf_valid_reg && !mcf_ready; - - stat_tx_lfc_pkt_next = 1'b0; - stat_tx_lfc_xon_next = 1'b0; - stat_tx_lfc_xoff_next = 1'b0; - stat_tx_pfc_pkt_next = 1'b0; - stat_tx_pfc_xon_next = 0; - stat_tx_pfc_xoff_next = 0; - - if (cfg_quanta_clk_en) begin - if (lfc_refresh_reg > cfg_quanta_step) begin - lfc_refresh_next = lfc_refresh_reg - cfg_quanta_step; - end else begin - lfc_refresh_next = 0; - if (lfc_req_reg) begin - lfc_send_next = 1'b1; - end - end - end else begin - lfc_refresh_next = lfc_refresh_reg; - end - - for (k = 0; k < 8; k = k + 1) begin - if (cfg_quanta_clk_en) begin - if (pfc_refresh_reg[k] > cfg_quanta_step) begin - pfc_refresh_next[k] = pfc_refresh_reg[k] - cfg_quanta_step; - end else begin - pfc_refresh_next[k] = 0; - if (pfc_req_reg[k]) begin - pfc_send_next = 1'b1; - end - end - end else begin - pfc_refresh_next[k] = pfc_refresh_reg[k]; - end - end - - if (cfg_tx_lfc_en) begin - if (!mcf_valid_reg) begin - if (lfc_req_reg != tx_lfc_req) begin - lfc_req_next = tx_lfc_req; - lfc_act_next = lfc_act_reg | tx_lfc_req; - lfc_send_next = 1'b1; - end - - if (lfc_send_reg && !(PFC_ENABLE && cfg_tx_pfc_en && pfc_send_reg)) begin - mcf_pfc_sel_next = 1'b0; - mcf_valid_next = lfc_act_reg; - lfc_act_next = lfc_req_reg; - lfc_refresh_next = lfc_req_reg ? {cfg_tx_lfc_refresh, {QFB{1'b0}}} : 0; - lfc_send_next = 1'b0; - - stat_tx_lfc_pkt_next = lfc_act_reg; - stat_tx_lfc_xon_next = lfc_act_reg && !lfc_req_reg; - stat_tx_lfc_xoff_next = lfc_act_reg && lfc_req_reg; - end - end - end - - if (PFC_ENABLE && cfg_tx_pfc_en) begin - if (!mcf_valid_reg) begin - if (pfc_req_reg != tx_pfc_req) begin - pfc_req_next = tx_pfc_req; - pfc_act_next = pfc_act_reg | tx_pfc_req; - pfc_send_next = 1'b1; - end - - if (pfc_send_reg) begin - mcf_pfc_sel_next = 1'b1; - mcf_valid_next = pfc_act_reg != 0; - pfc_en_next = pfc_act_reg; - pfc_act_next = pfc_req_reg; - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_next[k] = pfc_req_reg[k] ? {cfg_tx_pfc_refresh[16*k +: 16], {QFB{1'b0}}} : 0; - end - pfc_send_next = 1'b0; - - stat_tx_pfc_pkt_next = pfc_act_reg != 0; - stat_tx_pfc_xon_next = pfc_act_reg & ~pfc_req_reg; - stat_tx_pfc_xoff_next = pfc_act_reg & pfc_req_reg; - end - end - end -end - -always @(posedge clk) begin - lfc_req_reg <= lfc_req_next; - lfc_act_reg <= lfc_act_next; - lfc_send_reg <= lfc_send_next; - pfc_req_reg <= pfc_req_next; - pfc_act_reg <= pfc_act_next; - pfc_en_reg <= pfc_en_next; - pfc_send_reg <= pfc_send_next; - - mcf_pfc_sel_reg <= mcf_pfc_sel_next; - mcf_valid_reg <= mcf_valid_next; - - lfc_refresh_reg <= lfc_refresh_next; - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_reg[k] <= pfc_refresh_next[k]; - end - - stat_tx_lfc_pkt_reg <= stat_tx_lfc_pkt_next; - stat_tx_lfc_xon_reg <= stat_tx_lfc_xon_next; - stat_tx_lfc_xoff_reg <= stat_tx_lfc_xoff_next; - stat_tx_pfc_pkt_reg <= stat_tx_pfc_pkt_next; - stat_tx_pfc_xon_reg <= stat_tx_pfc_xon_next; - stat_tx_pfc_xoff_reg <= stat_tx_pfc_xoff_next; - - if (rst) begin - lfc_req_reg <= 1'b0; - lfc_act_reg <= 1'b0; - lfc_send_reg <= 1'b0; - pfc_req_reg <= 0; - pfc_act_reg <= 0; - pfc_send_reg <= 0; - mcf_pfc_sel_reg <= PFC_ENABLE != 0; - mcf_valid_reg <= 1'b0; - lfc_refresh_reg <= 0; - for (k = 0; k < 8; k = k + 1) begin - pfc_refresh_reg[k] <= 0; - end - - stat_tx_lfc_pkt_reg <= 1'b0; - stat_tx_lfc_xon_reg <= 1'b0; - stat_tx_lfc_xoff_reg <= 1'b0; - stat_tx_pfc_pkt_reg <= 1'b0; - stat_tx_pfc_xon_reg <= 0; - stat_tx_pfc_xoff_reg <= 0; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/mii_phy_if.sv b/src/rvvi/mii_phy_if.sv deleted file mode 100644 index f3857ed06..000000000 --- a/src/rvvi/mii_phy_if.sv +++ /dev/null @@ -1,140 +0,0 @@ -/* - -Copyright (c) 2019 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * MII PHY interface - */ -module mii_phy_if # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2" -) -( - input wire rst, - - /* - * MII interface to MAC - */ - output wire mac_mii_rx_clk, - output wire mac_mii_rx_rst, - output wire [3:0] mac_mii_rxd, - output wire mac_mii_rx_dv, - output wire mac_mii_rx_er, - output wire mac_mii_tx_clk, - output wire mac_mii_tx_rst, -(* mark_debug = "true" *) input wire [3:0] mac_mii_txd, -(* mark_debug = "true" *) input wire mac_mii_tx_en, - input wire mac_mii_tx_er, - - /* - * MII interface to PHY - */ - input wire phy_mii_rx_clk, - input wire [3:0] phy_mii_rxd, - input wire phy_mii_rx_dv, - input wire phy_mii_rx_er, - input wire phy_mii_tx_clk, - output wire [3:0] phy_mii_txd, - output wire phy_mii_tx_en, - output wire phy_mii_tx_er -); - -ssio_sdr_in # -( - .TARGET(TARGET), - .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), - .WIDTH(6) -) -rx_ssio_sdr_inst ( - .input_clk(phy_mii_rx_clk), - .input_d({phy_mii_rxd, phy_mii_rx_dv, phy_mii_rx_er}), - .output_clk(mac_mii_rx_clk), - .output_q({mac_mii_rxd, mac_mii_rx_dv, mac_mii_rx_er}) -); - -(* IOB = "TRUE" *) -reg [3:0] phy_mii_txd_reg = 4'd0; -(* IOB = "TRUE" *) -reg phy_mii_tx_en_reg = 1'b0, phy_mii_tx_er_reg = 1'b0; - -assign phy_mii_txd = phy_mii_txd_reg; -assign phy_mii_tx_en = phy_mii_tx_en_reg; -assign phy_mii_tx_er = phy_mii_tx_er_reg; - -always @(posedge mac_mii_tx_clk) begin - phy_mii_txd_reg <= mac_mii_txd; - phy_mii_tx_en_reg <= mac_mii_tx_en; - phy_mii_tx_er_reg <= mac_mii_tx_er; -end - -generate - -if (TARGET == "XILINX") begin - BUFG - mii_bufg_inst ( - .I(phy_mii_tx_clk), - .O(mac_mii_tx_clk) - ); -end else begin - assign mac_mii_tx_clk = phy_mii_tx_clk; -end - -endgenerate - -// reset sync -reg [3:0] tx_rst_reg = 4'hf; -assign mac_mii_tx_rst = tx_rst_reg[0]; - -always @(posedge mac_mii_tx_clk or posedge rst) begin - if (rst) begin - tx_rst_reg <= 4'hf; - end else begin - tx_rst_reg <= {1'b0, tx_rst_reg[3:1]}; - end -end - -reg [3:0] rx_rst_reg = 4'hf; -assign mac_mii_rx_rst = rx_rst_reg[0]; - -always @(posedge mac_mii_rx_clk or posedge rst) begin - if (rst) begin - rx_rst_reg <= 4'hf; - end else begin - rx_rst_reg <= {1'b0, rx_rst_reg[3:1]}; - end -end - -endmodule - -`resetall diff --git a/src/rvvi/ssio_ddr_in.sv b/src/rvvi/ssio_ddr_in.sv deleted file mode 100644 index 5060f4d27..000000000 --- a/src/rvvi/ssio_ddr_in.sv +++ /dev/null @@ -1,150 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * Generic source synchronous DDR input - */ -module ssio_ddr_in # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // IODDR style ("IODDR", "IODDR2") - // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale - // Use IODDR2 for Spartan-6 - parameter IODDR_STYLE = "IODDR2", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-6, 7-series - // Use BUFG for Virtex-5, Spartan-6, Ultrascale - parameter CLOCK_INPUT_STYLE = "BUFG", - // Width of register in bits - parameter WIDTH = 1 -) -( - input wire input_clk, - - input wire [WIDTH-1:0] input_d, - - output wire output_clk, - - output wire [WIDTH-1:0] output_q1, - output wire [WIDTH-1:0] output_q2 -); - -wire clk_int; -wire clk_io; - -generate - -if (TARGET == "XILINX") begin - - // use Xilinx clocking primitives - - if (CLOCK_INPUT_STYLE == "BUFG") begin - - // buffer RX clock - BUFG - clk_bufg ( - .I(input_clk), - .O(clk_int) - ); - - // pass through RX clock to logic and input buffers - assign clk_io = clk_int; - assign output_clk = clk_int; - - end else if (CLOCK_INPUT_STYLE == "BUFR") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to logic - BUFR #( - .BUFR_DIVIDE("BYPASS") - ) - clk_bufr ( - .I(clk_int), - .O(output_clk), - .CE(1'b1), - .CLR(1'b0) - ); - - end else if (CLOCK_INPUT_STYLE == "BUFIO") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to MAC - BUFG - clk_bufg ( - .I(clk_int), - .O(output_clk) - ); - - end - -end else begin - - // pass through RX clock to input buffers - assign clk_io = input_clk; - - // pass through RX clock to logic - assign clk_int = input_clk; - assign output_clk = clk_int; - -end - -endgenerate - -iddr #( - .TARGET(TARGET), - .IODDR_STYLE(IODDR_STYLE), - .WIDTH(WIDTH) -) -data_iddr_inst ( - .clk(clk_io), - .d(input_d), - .q1(output_q1), - .q2(output_q2) -); - -endmodule - -`resetall diff --git a/src/rvvi/ssio_sdr_in.sv b/src/rvvi/ssio_sdr_in.sv deleted file mode 100644 index 351cadc1d..000000000 --- a/src/rvvi/ssio_sdr_in.sv +++ /dev/null @@ -1,166 +0,0 @@ -/* - -Copyright (c) 2016-2018 Alex Forencich - -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. - -*/ - -// Language: Verilog 2001 - -`resetall -`default_nettype none - -/* - * Generic source synchronous SDR input - */ -module ssio_sdr_in # -( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") - // Use BUFR for Virtex-5, Virtex-6, 7-series - // Use BUFG for Ultrascale - // Use BUFIO2 for Spartan-6 - parameter CLOCK_INPUT_STYLE = "BUFIO2", - // Width of register in bits - parameter WIDTH = 1 -) -( - input wire input_clk, - - input wire [WIDTH-1:0] input_d, - - output wire output_clk, - - output wire [WIDTH-1:0] output_q -); - -wire clk_int; -wire clk_io; - -generate - -if (TARGET == "XILINX") begin - - // use Xilinx clocking primitives - - if (CLOCK_INPUT_STYLE == "BUFG") begin - - // buffer RX clock - BUFG - clk_bufg ( - .I(input_clk), - .O(clk_int) - ); - - // pass through RX clock to logic and input buffers - assign clk_io = clk_int; - assign output_clk = clk_int; - - end else if (CLOCK_INPUT_STYLE == "BUFR") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to logic - BUFR #( - .BUFR_DIVIDE("BYPASS") - ) - clk_bufr ( - .I(clk_int), - .O(output_clk), - .CE(1'b1), - .CLR(1'b0) - ); - - end else if (CLOCK_INPUT_STYLE == "BUFIO") begin - - assign clk_int = input_clk; - - // pass through RX clock to input buffers - BUFIO - clk_bufio ( - .I(clk_int), - .O(clk_io) - ); - - // pass through RX clock to MAC - BUFG - clk_bufg ( - .I(clk_int), - .O(output_clk) - ); - - end else if (CLOCK_INPUT_STYLE == "BUFIO2") begin - - // pass through RX clock to input buffers - BUFIO2 #( - .DIVIDE(1), - .DIVIDE_BYPASS("TRUE"), - .I_INVERT("FALSE"), - .USE_DOUBLER("FALSE") - ) - clk_bufio ( - .I(input_clk), - .DIVCLK(clk_int), - .IOCLK(clk_io), - .SERDESSTROBE() - ); - - // pass through RX clock to MAC - BUFG - clk_bufg ( - .I(clk_int), - .O(output_clk) - ); - - end - -end else begin - - // pass through RX clock to input buffers - assign clk_io = input_clk; - - // pass through RX clock to logic - assign clk_int = input_clk; - assign output_clk = clk_int; - -end - -endgenerate - -(* IOB = "TRUE" *) -reg [WIDTH-1:0] output_q_reg = {WIDTH{1'b0}}; - -assign output_q = output_q_reg; - -always @(posedge clk_io) begin - output_q_reg <= input_d; -end - -endmodule - -`resetall From 9471dcd296d7ba0dfe4bf8c791cc5f4db8242618 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 19 Jul 2024 17:08:47 -0500 Subject: [PATCH 091/163] Refactored the fpga and testbench so the RVVI can be synthesized cleanly and simulated without any major code changes. Adds three new configuration parameters to control enabling the RVVI packetizer and how much latency should exist between packets and the initial startup delay. --- .gitignore | 1 + config/derivlist.txt | 4 ++ config/rv32e/config.vh | 5 ++ config/rv32gc/config.vh | 5 ++ config/rv32i/config.vh | 5 ++ config/rv32imc/config.vh | 5 ++ config/rv64gc/config.vh | 5 ++ config/rv64i/config.vh | 5 ++ config/shared/parameter-defs.vh | 5 +- fpga/src/fpgaTopArtyA7.sv | 83 +++++++++++++++++++++++++++++- sim/questa/wally.do | 2 +- sim/verilator/Makefile | 6 +-- src/cvw.sv | 5 ++ src/hazard/hazard.sv | 4 +- src/rvvi/packetizer.sv | 7 +-- src/rvvi/rvvisynth.sv | 42 +++++++++------ src/wally/wallypipelinedcore.sv | 4 +- src/wally/wallypipelinedsoc.sv | 4 +- testbench/common/loggers.sv | 4 +- testbench/testbench.sv | 91 ++++++++++++++++++++++++++++++--- testbench/wallywrapper.sv | 6 +-- 21 files changed, 253 insertions(+), 45 deletions(-) diff --git a/.gitignore b/.gitignore index 9a5f1668c..3c4918418 100644 --- a/.gitignore +++ b/.gitignore @@ -237,3 +237,4 @@ tests/functcov tests/functcov/* tests/functcov/*/* sim/vcs/simprofile* +/fpga/rvvidaemon/rvvidaemon diff --git a/config/derivlist.txt b/config/derivlist.txt index 174ca5191..9535e9833 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -56,6 +56,10 @@ EXT_MEM_RANGE 64'h0FFFFFFF SDC_SUPPORTED 1 PLIC_SDC_ID 32'd20 BPRED_SIZE 32'd12 +RVVI_SYNTH_SUPPORTED 1 +RVVI_INIT_TIME_OUT 32'd100000000 +RVVI_PACKET_DELAY 32'd350 + # The syn configurations are trimmed down for faster synthesis. deriv syn_rv32e rv32e diff --git a/config/rv32e/config.vh b/config/rv32e/config.vh index 4ec0123d1..1234bbcdf 100644 --- a/config/rv32e/config.vh +++ b/config/rv32e/config.vh @@ -225,4 +225,9 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; +// debug tools +localparam logic RVVI_SYNTH_SUPPORTED = 0; +localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; +localparam [31:0] RVVI_PACKET_DELAY = 32'd2; + `include "config-shared.vh" diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index c861759d9..9f5809383 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -225,4 +225,9 @@ localparam DIVCOPIES = 32'd2; // Memory synthesis configuration localparam logic USE_SRAM = 0; +// debug tools +localparam logic RVVI_SYNTH_SUPPORTED = 0; +localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; +localparam [31:0] RVVI_PACKET_DELAY = 32'd2; + `include "config-shared.vh" diff --git a/config/rv32i/config.vh b/config/rv32i/config.vh index 01818afc2..6bfea805e 100644 --- a/config/rv32i/config.vh +++ b/config/rv32i/config.vh @@ -225,4 +225,9 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; +// debug tools +localparam logic RVVI_SYNTH_SUPPORTED = 0; +localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; +localparam [31:0] RVVI_PACKET_DELAY = 32'd2; + `include "config-shared.vh" diff --git a/config/rv32imc/config.vh b/config/rv32imc/config.vh index 05a8fd242..3918c702c 100644 --- a/config/rv32imc/config.vh +++ b/config/rv32imc/config.vh @@ -225,4 +225,9 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; +// debug tools +localparam logic RVVI_SYNTH_SUPPORTED = 0; +localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; +localparam [31:0] RVVI_PACKET_DELAY = 32'd2; + `include "config-shared.vh" diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index b8ed8dc47..86036aaa7 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -225,4 +225,9 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; +// debug tools +localparam logic RVVI_SYNTH_SUPPORTED = 0; +localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; +localparam [31:0] RVVI_PACKET_DELAY = 32'd2; + `include "config-shared.vh" diff --git a/config/rv64i/config.vh b/config/rv64i/config.vh index 94360877f..0e13f9ea1 100644 --- a/config/rv64i/config.vh +++ b/config/rv64i/config.vh @@ -225,4 +225,9 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; +// debug tools +localparam logic RVVI_SYNTH_SUPPORTED = 0; +localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; +localparam [31:0] RVVI_PACKET_DELAY = 32'd2; + `include "config-shared.vh" diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index 3dd067b34..099f49287 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -199,5 +199,8 @@ localparam cvw_t P = '{ FPDUR : FPDUR, DURLEN : DURLEN, DIVb : DIVb, - DIVBLEN : DIVBLEN + DIVBLEN : DIVBLEN, + RVVI_SYNTH_SUPPORTED : RVVI_SYNTH_SUPPORTED, + RVVI_INIT_TIME_OUT : RVVI_INIT_TIME_OUT, + RVVI_PACKET_DELAY : RVVI_PACKET_DELAY }; diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index e5a706d0d..7fe0a13b0 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -513,7 +513,7 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr, .RVVIStall); + .UARTSin, .UARTSout, .SDCIntr, .ExternalStall(RVVIStall)); // ahb lite to axi bridge @@ -1116,10 +1116,89 @@ module fpgaTop .device_temp(device_temp)); localparam MAX_CSRS = 3; + localparam TOTAL_CSRS = 36; + + // pipeline controlls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + (* mark_debug = "true" *) logic valid; logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; - rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .valid, .rvvi); + assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; + assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; + assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; + assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; + assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; + assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; + assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; + assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; + assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; + assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; + assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; + assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; + assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; + assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; + assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; + assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); // axi 4 write data channel (* mark_debug = "true" *) logic [31:0] RvviAxiWdata; diff --git a/sim/questa/wally.do b/sim/questa/wally.do index a0e6fdbb6..71a25856d 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -193,7 +193,7 @@ set temp3 [lindex $PlusArgs 3] # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${idvFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 +vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${idvFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals diff --git a/sim/verilator/Makefile b/sim/verilator/Makefile index ba8470548..e6bde7b41 100644 --- a/sim/verilator/Makefile +++ b/sim/verilator/Makefile @@ -25,7 +25,7 @@ TARGET=$(WORKING_DIR)/target # INCLUDE_PATH are pathes that Verilator should search for files it needs INCLUDE_PATH="-I${WALLY}/config/shared" "-I${WALLY}/config/$(WALLYCONF)" "-I${WALLY}/config/deriv/$(WALLYCONF)" # SOURCES are source files -SOURCES=${WALLY}/src/cvw.sv ${WALLY}/testbench/${TESTBENCH}.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv +SOURCES=${WALLY}/src/cvw.sv ${WALLY}/testbench/${TESTBENCH}.sv ${WALLY}/testbench/common/*.sv ${WALLY}/src/*/*.sv ${WALLY}/src/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv # DEPENDENCIES are configuration files and source files, which leads to recompilation of executables DEPENDENCIES=${WALLY}/config/shared/*.vh $(SOURCES) @@ -45,7 +45,7 @@ default: run run: wkdir/$(WALLYCONF)_$(TEST)/V${TESTBENCH} mkdir -p $(VERILATOR_DIR)/logs wkdir/$(WALLYCONF)_$(TEST)/V${TESTBENCH} ${ARGTEST} - + profile: obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF) $(VERILATOR_DIR)/obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF) ${ARGTEST} mv gmon.out gmon_$(WALLYCONF).out @@ -82,4 +82,4 @@ obj_dir_profiling/V${TESTBENCH}_$(WALLYCONF): $(DEPENDENCIES) $(SOURCES) clean: - rm -rf $(VERILATOR_DIR)/wkdir $(VERILATOR_DIR)/obj_dir_profiling $(VERILATOR_DIR)/logs $(VERILATOR_DIR)/logs_profiling \ No newline at end of file + rm -rf $(VERILATOR_DIR)/wkdir $(VERILATOR_DIR)/obj_dir_profiling $(VERILATOR_DIR)/logs $(VERILATOR_DIR)/logs_profiling diff --git a/src/cvw.sv b/src/cvw.sv index a06feb0b9..612996654 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -294,6 +294,11 @@ typedef struct packed { int DURLEN ; int DIVb ; int DIVBLEN ; + +// debug tools + logic RVVI_SYNTH_SUPPORTED; + logic [31:0] RVVI_INIT_TIME_OUT; + logic [31:0] RVVI_PACKET_DELAY; } cvw_t; endpackage diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index ed3b6da3a..46ff433cf 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -31,7 +31,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, input logic StructuralStallD, input logic LSUStallM, IFUStallF, - input logic FPUStallD, RVVIStall, + input logic FPUStallD, ExternalStall, input logic DivBusyE, FDivBusyE, input logic wfiM, IntPendingM, // Stall & flush outputs @@ -89,7 +89,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1. // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. - assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | RVVIStall; + assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | ExternalStall; // Stall each stage for cause or if the next stage is stalled // coverage off: StallFCause is always 0 diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 0d33947c1..cf99b9038 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -100,11 +100,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, // have to count at least 250 ms after reset pulled to wait for the phy to actually be ready // at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000. counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); - assign CountFlag = RstCount == 32'd100000000; - //assign CountFlag = RstCount == 32'd10; - //assign DelayFlag = RstCount == 32'd800; - assign DelayFlag = RstCount == 32'd350; - //assign DelayFlag = RstCount == 32'd0; + assign CountFlag = RstCount == P.RVVI_INIT_TIME_OUT; + assign DelayFlag = RstCount == P.RVVI_PACKET_DELAY; counter #(32) framecounter(m_axi_aclk, ~m_axi_aresetn, (RvviAxiWready & RvviAxiWlast), FrameCount); diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index 16b214e18..7700cc615 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -27,32 +27,38 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -`define FPGA 1 +`define FPGA 0 module rvvisynth import cvw::*; #(parameter cvw_t P, - parameter integer MAX_CSRS)( + parameter integer MAX_CSRS, TOTAL_CSRS = 36)( input logic clk, reset, + input logic StallE, StallM, StallW, FlushE, FlushM, FlushW, + // required + input logic [P.XLEN-1:0] PCM, + input logic InstrValidM, + input logic [31:0] InstrRawD, + input logic [63:0] Mcycle, Minstret, + input logic TrapM, + input logic [1:0] PrivilegeModeW, + // registers gpr and fpr + input logic GPRWen, FPRWen, + input logic [4:0] GPRAddr, FPRAddr, + input logic [P.XLEN-1:0] GPRValue, FPRValue, + input logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0], output logic valid, output logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi ); - localparam TOTAL_CSRS = 36; - // pipeline controlls - logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required - logic [P.XLEN-1:0] PCM, PCW; - logic InstrValidM, InstrValidW; - logic [31:0] InstrRawD, InstrRawE, InstrRawM, InstrRawW; - logic [63:0] Mcycle, Minstret; - logic TrapM, TrapW; - logic [1:0] PrivilegeModeW; + logic [P.XLEN-1:0] PCW; + logic InstrValidW; + logic [31:0] InstrRawE, InstrRawM, InstrRawW; + logic TrapW; + // registers gpr and fpr - logic GPRWen, FPRWen; - logic [4:0] GPRAddr, FPRAddr; - logic [P.XLEN-1:0] GPRValue, FPRValue; logic [P.XLEN-1:0] XLENZeros; - logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; logic [TOTAL_CSRS-1:0] CSRArrayWen; logic [P.XLEN-1:0] CSRValue [MAX_CSRS-1:0]; logic [TOTAL_CSRS-1:0] CSRWen [MAX_CSRS-1:0]; @@ -61,10 +67,11 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [11:0] CSRCount; logic [177+P.XLEN-1:0] Required; logic [10+2*P.XLEN-1:0] Registers; - logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; + logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; // get signals from the core. if (`FPGA) begin +/* -----\/----- EXCLUDED -----\/----- assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; @@ -123,7 +130,9 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + -----/\----- EXCLUDED -----/\----- */ end else begin // if (`FPGA) +/* -----\/----- EXCLUDED -----\/----- assign StallE = dut.core.StallE; assign StallM = dut.core.StallM; assign StallW = dut.core.StallW; @@ -182,6 +191,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + -----/\----- EXCLUDED -----/\----- */ end // diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 30efbe90b..fac30193c 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -45,7 +45,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( output logic [3:0] HPROT, output logic [1:0] HTRANS, output logic HMASTLOCK, - input logic RVVIStall + input logic ExternalStall ); logic StallF, StallD, StallE, StallM, StallW; @@ -275,7 +275,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .StructuralStallD, .LSUStallM, .IFUStallF, - .FPUStallD, .RVVIStall, + .FPUStallD, .ExternalStall, .DivBusyE, .FDivBusyE, .wfiM, .IntPendingM, // Stall & flush outputs diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 236a653fb..bda183bf9 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -37,7 +37,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( output logic HSELEXT, output logic HSELEXTSDC, // fpga debug signals - input logic RVVIStall, + input logic ExternalStall, // outputs to external memory, shared with uncore memory output logic HCLK, HRESETn, output logic [P.PA_BITS-1:0] HADDR, @@ -77,7 +77,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( wallypipelinedcore #(P) core(.clk, .reset, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, - .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .RVVIStall + .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .ExternalStall ); // instantiate uncore if a bus interface exists diff --git a/testbench/common/loggers.sv b/testbench/common/loggers.sv index b8a6389cb..967cf672b 100644 --- a/testbench/common/loggers.sv +++ b/testbench/common/loggers.sv @@ -261,11 +261,11 @@ module loggers import cvw::*; #(parameter cvw_t P, $fwrite(file, "BEGIN %s\n", memfilename); $fwrite(CFIfile, "BEGIN %s\n", memfilename); end - if(dut.core.ifu.InstrClassM[0] & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin + if(dut.core.ifu.IClassM[0] & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin direction = PCSrcM ? "t" : "n"; $fwrite(file, "%h %s\n", dut.core.PCM, direction); end - if((|dut.core.ifu.InstrClassM) & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin + if((|dut.core.ifu.IClassM) & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin direction = PCSrcM ? "t" : "n"; $fwrite(CFIfile, "%h %s\n", dut.core.PCM, direction); end diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 098280423..a109b1c6f 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -580,7 +580,8 @@ module testbench; assign SDCIntr = 1'b0; end - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .RVVIStall, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall(RVVIStall), + .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS); @@ -590,12 +591,91 @@ module testbench; clk = 1'b1; # 5; clk = 1'b0; # 5; end - if(`RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + if(P.RVVI_SYNTH_SUPPORTED) begin : rvvi_synth localparam MAX_CSRS = 3; logic valid; logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; - rvvisynth #(P, MAX_CSRS) rvvisynth(.clk, .reset, .valid, .rvvi); + localparam TOTAL_CSRS = 36; + + // pipeline controlls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + + assign StallE = dut.core.StallE; + assign StallM = dut.core.StallM; + assign StallW = dut.core.StallW; + assign FlushE = dut.core.FlushE; + assign FlushM = dut.core.FlushM; + assign FlushW = dut.core.FlushW; + assign InstrValidM = dut.core.ieu.InstrValidM; + assign InstrRawD = dut.core.ifu.InstrRawD; + assign PCM = dut.core.ifu.PCM; + assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = dut.core.TrapM; + assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = dut.core.ieu.dp.regf.a3; + assign GPRWen = dut.core.ieu.dp.regf.we3; + assign GPRValue = dut.core.ieu.dp.regf.wd3; + assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + + rvvisynth #(P, MAX_CSRS, TOTAL_CSRS) rvvisynth(.clk, .reset, .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); // axi 4 write data channel logic [31:0] RvviAxiWdata; @@ -618,12 +698,11 @@ module testbench; .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), .rx_axis_tlast(), .rx_axis_tuser(), - // *** update these - .mii_rx_clk(clk), // *** need to be the mii clock + .mii_rx_clk(clk), .mii_rxd('0), .mii_rx_dv('0), .mii_rx_er('0), - .mii_tx_clk(clk), // *** needs to be the mii clock + .mii_tx_clk(clk), .mii_txd, .mii_tx_en, .mii_tx_er, diff --git a/testbench/wallywrapper.sv b/testbench/wallywrapper.sv index 234a11fdf..0cf6940fb 100644 --- a/testbench/wallywrapper.sv +++ b/testbench/wallywrapper.sv @@ -57,7 +57,7 @@ module wallywrapper; logic HREADY; logic HSELEXT; logic HSELEXTSDC; - logic RVVIStall; + logic ExternalStall; // instantiate device to be tested assign GPIOIN = 0; @@ -67,9 +67,9 @@ module wallywrapper; assign HRESPEXT = 0; assign HRDATAEXT = 0; - assign RVVIStall = '0; + assign ExternalStall = '0; - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .RVVIStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr); From 00840e489372abf6669eb6ffb69a98803ab443f8 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Fri, 19 Jul 2024 17:35:30 -0500 Subject: [PATCH 092/163] Made the fpga top level configurable between rvvi synth and not. --- fpga/constraints/small-debug.xdc | 50 +------- fpga/src/fpgaTopArtyA7.sv | 200 ++++++++++++++++--------------- 2 files changed, 108 insertions(+), 142 deletions(-) diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index ce824620b..6fef2ba79 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -21,60 +21,22 @@ set_property port_width 32 [get_debug_ports u_ila_0/probe0] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] + create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe1] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] -connect_debug_port u_ila_0/probe1 [get_nets [list RvviAxiWlast ]] +connect_debug_port u_ila_0/probe1 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe2] +set_property port_width 64 [get_debug_ports u_ila_0/probe2] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] -connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] +connect_debug_port u_ila_0/probe2 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] + create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe3] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] -connect_debug_port u_ila_0/probe3 [get_nets [list {RvviAxiRlast}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe4] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] -connect_debug_port u_ila_0/probe4 [get_nets [list {RvviAxiRvalid}]] - -create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe5] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] -connect_debug_port u_ila_0/probe5 [get_nets [list {packetizer/CurrState[0]} {packetizer/CurrState[1]} {packetizer/CurrState[2]} {packetizer/CurrState[3]}]] - -create_debug_port u_ila_0 probe -set_property port_width 64 [get_debug_ports u_ila_0/probe6] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] -connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe7] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] -connect_debug_port u_ila_0/probe7 [get_nets [list {RvviAxiWvalid}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe8] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] -connect_debug_port u_ila_0/probe8 [get_nets [list {RVVIStall}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe9] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] -connect_debug_port u_ila_0/probe9 [get_nets [list {valid}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe10] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] -connect_debug_port u_ila_0/probe10 [get_nets [list {RvviAxiWready}]] - -create_debug_port u_ila_0 probe -set_property port_width 3 [get_debug_ports u_ila_0/probe11] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] -connect_debug_port u_ila_0/probe11 [get_nets [list {triggergen/CurrState[0]} {triggergen/CurrState[1]} {triggergen/CurrState[2]}]] +connect_debug_port u_ila_0/probe3 [get_nets [list {RVVIStall}]] # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 7fe0a13b0..48a02fb89 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -78,7 +78,7 @@ module fpgaTop wire CPUCLK; wire c0_ddr4_ui_clk_sync_rst; -(* mark_debug = "true" *) wire bus_struct_reset; + wire bus_struct_reset; wire peripheral_reset; wire interconnect_aresetn; wire peripheral_aresetn; @@ -1114,109 +1114,110 @@ module fpgaTop .init_calib_complete(c0_init_calib_complete), .device_temp(device_temp)); - - localparam MAX_CSRS = 3; - localparam TOTAL_CSRS = 36; - - // pipeline controlls - logic StallE, StallM, StallW, FlushE, FlushM, FlushW; - // required - logic [P.XLEN-1:0] PCM; - logic InstrValidM; - logic [31:0] InstrRawD; - logic [63:0] Mcycle, Minstret; - logic TrapM; - logic [1:0] PrivilegeModeW; - // registers gpr and fpr - logic GPRWen, FPRWen; - logic [4:0] GPRAddr, FPRAddr; - logic [P.XLEN-1:0] GPRValue, FPRValue; - logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; -(* mark_debug = "true" *) logic valid; - logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + if(P.RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + localparam MAX_CSRS = 3; + localparam TOTAL_CSRS = 36; + + // pipeline controlls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; - assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; - assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; - assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; - assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; - assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; - assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; - assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; - assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; - assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; - assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; - assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; - assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; - assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; - assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; - assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; - assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; + logic valid; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; - assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 - assign CSRArray[16] = 0; // 12'hF11 - assign CSRArray[17] = 0; // 12'hF12 - assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 - assign CSRArray[19] = 0; // 12'hF15 - assign CSRArray[20] = 0; // 12'h34A - // supervisor CSRs - assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D - // user CSRs - assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; + assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; + assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; + assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; + assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; + assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; + assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; + assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; + assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; + assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; + assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; + assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; + assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; + assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; + assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; + assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; - rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, - .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, - .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, - .valid, .rvvi); + assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 - // axi 4 write data channel -(* mark_debug = "true" *) logic [31:0] RvviAxiWdata; -(* mark_debug = "true" *) logic [3:0] RvviAxiWstrb; -(* mark_debug = "true" *) logic RvviAxiWlast; -(* mark_debug = "true" *) logic RvviAxiWvalid; -(* mark_debug = "true" *) logic RvviAxiWready; + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); -(* mark_debug = "true" *) logic [31:0] RvviAxiRdata; - logic [3:0] RvviAxiRstrb; -(* mark_debug = "true" *) logic RvviAxiRlast; -(* mark_debug = "true" *) logic RvviAxiRvalid; -(* mark_debug = "true" *) logic IlaTrigger; - + // axi 4 write data channel + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; + + logic [31:0] RvviAxiRdata; + logic [3:0] RvviAxiRstrb; + logic RvviAxiRlast; + logic RvviAxiRvalid; + (* mark_debug = "true" *) logic IlaTrigger; + - logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; - logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); @@ -1242,8 +1243,11 @@ module fpgaTop .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) ); - triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, - .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger); + triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, + .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger); + end else begin // if (P.RVVI_SYNTH_SUPPORTED) + assign RVVIStall = '0; + end //assign phy_reset_n = ~bus_struct_reset; assign phy_reset_n = ~1'b0; From c7d869bc96022e4731fa305ec94c9e6e881f4dce Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Sat, 20 Jul 2024 14:00:43 -0500 Subject: [PATCH 093/163] Added inital spi based sd card code. Working on CRC7 code that works. --- fpga/zsbl/sd.c | 31 +++++++++++++++++++++++++++++++ fpga/zsbl/sd.h | 9 +++++++++ fpga/zsbl/spi.c | 1 - fpga/zsbl/spi.h | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 fpga/zsbl/sd.c create mode 100644 fpga/zsbl/sd.h diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c new file mode 100644 index 000000000..4ffb53d67 --- /dev/null +++ b/fpga/zsbl/sd.c @@ -0,0 +1,31 @@ +#include "sd.h" +#include "spi.h" + +uint8_t crc7(uint8_t prev, uint8_t in) { + // CRC polynomial 0x89 + uint8_t remainder = prev & in; + remainder ^= (remainder >> 4) ^ (remainder >> 7); + remainder ^= remainder << 4; + return remainder & 0x7f; +} + +uint16_t crc16(uint16_t crc, uint8_t data) { + // CRC polynomial 0x11021 + crc = (uint8_t)(crc >> 8) | (crc << 8); + crc ^= data; + crc ^= (uint8_t)(crc >> 4) & 0xf; + crc ^= crc << 12; + crc ^= (crc & 0xff) << 5; + return crc; +} + +uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { + spi_send_byte +} + +void init_sd(){ + init_spi(); + + +} + diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h new file mode 100644 index 000000000..b1b27db14 --- /dev/null +++ b/fpga/zsbl/sd.h @@ -0,0 +1,9 @@ +#pragma once + +#include <stdint.h> + +uint8_t crc7(uint8_t prev, uint8_t in); +uint16_t crc16(uint16_t crc, uint8_t data); +uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); +void init_sd(); + diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 1400b8881..bf6d629b4 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -48,4 +48,3 @@ uint8_t spi_send_byte(uint8_t byte) { return result; } - diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index 2bd2003c5..6bae450ae 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -40,6 +40,7 @@ void write_reg(uintptr_t addr, uint32_t value); uint32_t read_reg(uintptr_t addr); uint8_t spi_send_byte(uint8_t byte); + void spi_init(); #endif From f30cc46ec52dec95b6222a5b6479593084e4401e Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Sun, 21 Jul 2024 08:26:07 -0700 Subject: [PATCH 094/163] Disable misaligned accesses in imperas configuration and check misaligned support requires D$ --- config/derivlist.txt | 2 ++ testbench/common/riscvassertions.sv | 1 + 2 files changed, 3 insertions(+) diff --git a/config/derivlist.txt b/config/derivlist.txt index 2fac6bcc2..1edd20b7b 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -1661,6 +1661,7 @@ derive imperas rv64gc ICACHE_SUPPORTED 0 DCACHE_SUPPORTED 0 VIRTMEM_SUPPORTED 0 +ZICCLSM_SUPPORTED 0 ZAAMO_SUPPORTED 0 ZALRSC_SUPPORTED 0 ZICBOM_SUPPORTED 0 @@ -1669,3 +1670,4 @@ SVPBMT_SUPPORTED 0 SVNAPOT_SUPPORTED 0 BOOTROM_BASE 64'h700012340010 BOOTROM_RANGE 64'h10 + diff --git a/testbench/common/riscvassertions.sv b/testbench/common/riscvassertions.sv index 404353909..0872ab1de 100644 --- a/testbench/common/riscvassertions.sv +++ b/testbench/common/riscvassertions.sv @@ -66,6 +66,7 @@ module riscvassertions import cvw::*; #(parameter cvw_t P); assert ((P.ZCF_SUPPORTED == 0) | ((P.F_SUPPORTED == 1) & (P.XLEN == 32))) else $fatal(1, "ZCF requires F and XLEN == 32"); assert ((P.ZCD_SUPPORTED == 0) | (P.D_SUPPORTED == 1)) else $fatal(1, "ZCD requires D"); assert ((P.LLEN == P.XLEN) | (P.DCACHE_SUPPORTED & P.DTIM_SUPPORTED == 0)) else $fatal(1, "LLEN > XLEN (D on RV32 or Q on RV64) requires data cache"); + assert ((P.ZICCLSM_SUPPORTED == 0) | (P.DCACHE_SUPPORTED == 1)) else $fatal(1, "ZICCLSM requires DCACHE_SUPPORTED"); end endmodule From 7fd8c6e29ae08d2f2ef0a00861527db5479d75b4 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Sun, 21 Jul 2024 19:45:22 -0700 Subject: [PATCH 095/163] Removed outdated wally-imperas files --- sim/questa/sim-imperas | 33 ------------- sim/questa/wally-imperas-cov.do | 79 ------------------------------ sim/questa/wally-imperas-no-idv.do | 48 ------------------ sim/questa/wally-imperas.do | 64 ------------------------ 4 files changed, 224 deletions(-) delete mode 100755 sim/questa/sim-imperas delete mode 100644 sim/questa/wally-imperas-cov.do delete mode 100644 sim/questa/wally-imperas-no-idv.do delete mode 100644 sim/questa/wally-imperas.do diff --git a/sim/questa/sim-imperas b/sim/questa/sim-imperas deleted file mode 100755 index 556cdebf6..000000000 --- a/sim/questa/sim-imperas +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -########################################### -## imperas-one-time.sh -## -## Written: Ross Thompson (ross1728@gmail.com) and Lee Moore (moore@imperas.com) -## Created: 31 January 2023 -## Modified: 31 January 2023 -## -## Purpose: Run wally with imperas -## -## A component of the CORE-V-WALLY configurable RISC-V project. -## https://github.com/openhwgroup/cvw -## -## Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University -## -## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -## -## Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -## except in compliance with the License, or, at your option, the Apache License version 2.0. You -## may obtain a copy of the License at -## -## https://solderpad.org/licenses/SHL-2.1/ -## -## Unless required by applicable law or agreed to in writing, any work distributed under the -## License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -## either express or implied. See the License for the specific language governing permissions -## and limitations under the License. -################################################################################################ -IMPERAS_TOOLS=$(pwd)/imperas.ic \ -OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \ -TESTDIR=${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege/src/Lee.S/ \ -vsim -do "do wally-imperas.do rv64gc" diff --git a/sim/questa/wally-imperas-cov.do b/sim/questa/wally-imperas-cov.do deleted file mode 100644 index 1b83950d0..000000000 --- a/sim/questa/wally-imperas-cov.do +++ /dev/null @@ -1,79 +0,0 @@ -# wally.do -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench -# James Stine, 2008; David Harris 2021 -# Go Cowboys!!!!!! -# -# Takes 1:10 to run RV64IC tests using gui - -onbreak {resume} - -# create library -if [file exists work] { - vdel -all -} -vlib work - -# compile source files -# suppress spurious warnngs about -# "Extra checking for conflicts with always_comb done at vopt time" -# because vsim will run vopt - -# start and run simulation -# remove +acc flag for faster sim during regressions if there is no need to access internal signals - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. -vlog +incdir+$env(WALLY)/config/$1 \ - +incdir+$env(WALLY)/config/deriv/$1 \ - +incdir+$env(WALLY)/config/shared \ - +define+USE_IMPERAS_DV \ - +define+IDV_INCLUDE_TRACE2COV \ - +define+INCLUDE_TRACE2COV +define+COVER_BASE_RV64I +define+COVER_LEVEL_DV_PR_EXT \ - +define+COVER_RV64I \ - +define+COVER_RV64M \ - +define+COVER_RV64A \ - +define+COVER_RV64F \ - +define+COVER_RV64D \ - +define+COVER_RV64ZICSR \ - +define+COVER_RV64C \ - +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \ - +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviApiPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviTrace.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2api.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2log.sv \ - \ - +incdir+$env(IMPERAS_HOME)/ImpProprietary/source/host/riscvISACOV/source \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \ - \ - $env(WALLY)/src/cvw.sv \ - $env(WALLY)/testbench/testbench.sv \ - $env(WALLY)/testbench/common/*.sv \ - $env(WALLY)/src/*/*.sv \ - $env(WALLY)/src/*/*/*.sv \ - -suppress 2583 \ - -suppress 7063 \ - +acc -vopt +acc work.testbench -G DEBUG=1 -o workopt -eval vsim workopt +nowarn3829 -fatal 7 \ - -sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \ - +ElfFile=$env(TESTDIR)/ref/ref.elf $env(OTHERFLAGS) +TRACE2COV_ENABLE=1 - -coverage save -onexit $env(WALLY)/sim/questa/riscv.ucdb - - -view wave -#-- display input and output signals as hexidecimal values -# add log -recursive /* -# do wave.do - -run -all - -noview $env(WALLY)/testbench/testbench-imperas.sv -view wave - -#quit -f diff --git a/sim/questa/wally-imperas-no-idv.do b/sim/questa/wally-imperas-no-idv.do deleted file mode 100644 index 47d8bf07b..000000000 --- a/sim/questa/wally-imperas-no-idv.do +++ /dev/null @@ -1,48 +0,0 @@ -# wally.do -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench -# James Stine, 2008; David Harris 2021 -# Go Cowboys!!!!!! -# -# Takes 1:10 to run RV64IC tests using gui - -onbreak {resume} - -# create library -if [file exists work] { - vdel -all -} -vlib work - -# compile source files -# suppress spurious warnngs about -# "Extra checking for conflicts with always_comb done at vopt time" -# because vsim will run vopt - -# start and run simulation -# remove +acc flag for faster sim during regressions if there is no need to access internal signals - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. -vlog +incdir+../config/$1 \ - +incdir+../config/shared \ - ../../external/ImperasDV-HMC/Imperas/ImpPublic/source/host/rvvi/rvviTrace.sv \ - ../src/cvw.sv \ - ../testbench/testbench_imperas.sv \ - ../testbench/common/*.sv \ - ../src/*/*.sv \ - ../src/*/*/*.sv \ - -suppress 2583 \ - -suppress 7063 -vopt +acc work.testbench -G DEBUG=1 -o workopt -eval vsim workopt +nowarn3829 -fatal 7 \ - +testDir=$env(TESTDIR) $env(OTHERFLAGS) -view wave -#-- display input and output signals as hexidecimal values -add log -recursive /* -do wave.do - -run -all - -noview ../testbench/testbench_imperas.sv -view wave diff --git a/sim/questa/wally-imperas.do b/sim/questa/wally-imperas.do deleted file mode 100644 index 118e44d10..000000000 --- a/sim/questa/wally-imperas.do +++ /dev/null @@ -1,64 +0,0 @@ -# wally.do -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench -# James Stine, 2008; David Harris 2021 -# Go Cowboys!!!!!! -# -# Takes 1:10 to run RV64IC tests using gui - -onbreak {resume} - -# create library -if [file exists work] { - vdel -all -} -vlib work - -# compile source files -# suppress spurious warnngs about -# "Extra checking for conflicts with always_comb done at vopt time" -# because vsim will run vopt - -# start and run simulation -# remove +acc flag for faster sim during regressions if there is no need to access internal signals - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. - -vlog +incdir+../config/$1 \ - +incdir+../config/shared \ - +define+USE_IMPERAS_DV \ - +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \ - +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviApiPkg.sv \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviTrace.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2api.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2log.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \ - ../src/cvw.sv \ - ../testbench/testbench-imperas.sv \ - ../testbench/common/*.sv \ - ../src/*/*.sv \ - ../src/*/*/*.sv \ - -suppress 2583 \ - -suppress 7063 - -vopt +acc work.testbench -G DEBUG=1 -o workopt -eval vsim workopt +nowarn3829 -fatal 7 \ - -sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \ - +testDir=$env(TESTDIR) $env(OTHERFLAGS) -view wave -#-- display input and output signals as hexidecimal values -add log -recursive /* -do wave.do - -run -all - -noview ../testbench/testbench_imperas.sv -view wave - -#quit -f From af79fd57023ab412495de1847c4aca66a5b62475 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Sun, 21 Jul 2024 19:46:30 -0700 Subject: [PATCH 096/163] Fixed hazard and rd_maxval coverage generation --- tests/testgen/covergen.py | 165 +++++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 65 deletions(-) diff --git a/tests/testgen/covergen.py b/tests/testgen/covergen.py index 1e06e7b9c..0f7bb0d4e 100755 --- a/tests/testgen/covergen.py +++ b/tests/testgen/covergen.py @@ -37,7 +37,7 @@ def signedImm20(imm): imm = imm - 0x100000 return str(imm) -def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen): +def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen): lines = "\n# Testcase " + str(desc) + "\n" if (rs1val < 0): rs1val = rs1val + 2**xlen @@ -45,30 +45,31 @@ def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, stor rs2val = rs2val + 2**xlen lines = lines + "li x" + str(rd) + ", " + formatstr.format(rdval) + " # initialize rd to a random value that should get changed\n" if (test in rtype): - lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n" - lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value\n" + lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" + lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n" elif (test in shiftitype): - lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n" + lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\n" elif (test in itype): - lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value \n" + lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n" elif (test in loaditype):#["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" - lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # add immediate to lower part of rs1 \n" - lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" + lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # add immediate to lower part of rs1\n" + lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" elif (test in stypes):#["sb", "sh", "sw", "sd"] #lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" #lines = lines + test + " x" + str(rs2) + ", " "0(x" + str(rs1) + ") # perform operation \n" - print("Error: %s type not implemented yet" % test) + #print("Error: %s type not implemented yet" % test) + pass elif (test in btypes):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] if (randint(1,100) > 50): rs1val = rs2val lines = lines + "# same values in both registers\n" lines = lines + "nop\n" - lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1 to a random value that should get changed\n" - lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value that should get changed\n" + lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" + lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_sb_types_" + str(immval) + "+4" + " # perform operation \n" lines = lines + "addi x0, x1, 1\n" lines = lines + "some_label_for_sb_types_" + str(immval) + ":\n" @@ -79,6 +80,13 @@ def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, stor #print("Error: %s type not implemented yet" % test) f.write(lines) +def writeHazardVector(desc, rs1a, rs2a, rda, rs1b, rs2b, rdb, test): + # consecutive R-type instructions to trigger hazards + lines = "\n# Testcase " + str(desc) + "\n" + lines = lines + test + " x" + str(rda) + ", x" + str(rs1a) + ", x" + str(rs2a) + " # perform first operation\n" + lines = lines + test + " x" + str(rdb) + ", x" + str(rs1b) + ", x" + str(rs2b) + " # perform second operation\n" + f.write(lines) + def randomize(): rs1 = randint(1, 31) rs2 = randint(1, 31) @@ -93,157 +101,184 @@ def randomize(): rdval = randint(0, 2**xlen-1) return [rs1, rs2, rd, rs1val, rs2val, immval, rdval] -def make_rd(test, storecmd, xlen): +def make_rd(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rd (Test destination rd = x" + str(r) + ")" - writeCovVector(desc, rs1, rs2, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs1(test, storecmd, xlen): +def make_rs1(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rs1 (Test source rs1 = x" + str(r) + ")" - writeCovVector(desc, r, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, r, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs2(test, storecmd, xlen): +def make_rs2(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rs2 (Test source rs2 = x" + str(r) + ")" - writeCovVector(desc, rs1, r, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, r, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rd_rs1(test, storecmd, xlen): +def make_rd_rs1(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rd_rs1 (Test rd = rs1 = x" + str(r) + ")" - writeCovVector(desc, r, rs2, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, r, rs2, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rd_rs2(test, storecmd, xlen): +def make_rd_rs2(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rd_rs2 (Test rd = rs1 = x" + str(r) + ")" - writeCovVector(desc, rs1, r, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, r, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rd_rs1_rs2(test, storecmd, xlen): +def make_rd_rs1_rs2(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rd_rs1_rs2 (Test rd = rs1 = rs2 = x" + str(r) + ")" - writeCovVector(desc, r, r, r, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, r, r, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs1_rs2(test, storecmd, xlen): +def make_rs1_rs2(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rd_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")" - writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs1_maxvals(test, storecmd, xlen): +def make_rs1_maxvals(test, xlen): for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rs1_maxvals (Test source rs1 value = " + hex(v) + ")" - writeCovVector(desc, rs1, rs2, rd, v, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, v, rs2val, immval, rdval, test, xlen) -def make_rs2_maxvals(test, storecmd, xlen): +def make_rs2_maxvals(test, xlen): for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rs2_maxvals (Test source rs2 value = " + hex(v) + ")" - writeCovVector(desc, rs1, rs2, rd, rs1val, v, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, v, immval, rdval, test, xlen) -def make_rd_maxvals(test, storecmd, xlen): +def make_rd_maxvals(test, xlen): for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: + # rs1 = 0, rs2 = v, others are random [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" - writeCovVector(desc, rs1, 0, rd, v, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, 0, rd, v, rs2val, immval, rdval, test, xlen) + # rs1, rs2 = v, others are random + [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() + desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" + writeCovVector(desc, rs1, rs2, rd, v, v, immval, rdval, test, xlen) + # rs1 = all 1s, rs2 = v, others are random + [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() + desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" + writeCovVector(desc, rs1, rs2, rd, -1, v, immval, rdval, test, xlen) -def make_rd_rs1_eqval(test, storecmd, xlen): +def make_rd_rs1_eqval(test, xlen): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rdm_rs1_eqval (Test rs1 = rd = " + hex(rs1val) + ")" - writeCovVector(desc, rs1, 0, rd, rdval, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, 0, rd, rdval, rs2val, immval, rdval, test, xlen) -def make_rd_rs2_eqval(test, storecmd, xlen): +def make_rd_rs2_eqval(test, xlen): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rd_rs2_eqval (Test rs2 = rd = " + hex(rs2val) + ")" - writeCovVector(desc, 0, rs2, rd, rs1val, rdval, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, 0, rs2, rd, rs1val, rdval, immval, rdval, test, xlen) -def make_rs1_rs2_eqval(test, storecmd, xlen): +def make_rs1_rs2_eqval(test, xlen): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rs1_rs2_eqval (Test rs1 = rs2 = " + hex(rs1val) + ")" - writeCovVector(desc, rs1, rs2, rd, rs1val, rs1val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs1val, immval, rdval, test, xlen) -#def make_cp_gpr_hazard(test, storecmd, xlen): -# pass # *** to be implemented *** +def make_cp_gpr_hazard(test, xlen): + for haz in ["raw", "waw", "war"]: + for src in range(2): + [rs1a, rs2a, rda, rs1vala, rs2vala, immvala, rdvala] = randomize() + [rs1b, rs2b, rdb, rs1valb, rs2valb, immvalb, rdvalb] = randomize() + # set up hazard + if (haz == "raw"): + if (src): + rs2b = rda + else: + rs1b = rda + elif (haz == "waw"): + rdb = rda + elif (haz == "war"): + if (src): + rdb = rs2a + else: + rdb = rs1a + desc = "cmp_gpr_hazard " + haz + " test" + writeHazardVector(desc, rs1a, rs2a, rda, rs1b, rs2b, rdb, test) -def make_rs1_sign(test, storecmd, xlen): +def make_rs1_sign(test, xlen): for v in [1, -1]: [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() rs1val = abs(rs1val % 2**(xlen-1)) * v; desc = "cp_rs1_sign (Test source rs1 value = " + hex(rs1val) + ")" - writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs2_sign(test, storecmd, xlen): +def make_rs2_sign(test, xlen): for v in [1, -1]: [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() rs2val = abs(rs2val % 2**(xlen-1)) * v; desc = "cp_rs2_sign (Test source rs2 value = " + hex(rs2val) + ")" - writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_cr_rs1_rs2_sign(test, storecmd, xlen): +def make_cr_rs1_rs2_sign(test, xlen): for v1 in [1, -1]: for v2 in [1, -1]: [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() rs1val = abs(rs1val % 2**(xlen-1)) * v1; rs2val = abs(rs2val % 2**(xlen-1)) * v2; desc = "cr_rs1_rs2 (Test source rs1 = " + hex(rs1val) + " rs2 = " + hex(rs2val) + ")" - writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def write_tests(coverpoints, test, storecmd, xlen): +def write_tests(coverpoints, test, xlen): for coverpoint in coverpoints: if (coverpoint == "cp_asm_count"): pass elif (coverpoint == "cp_rd"): - make_rd(test, storecmd, xlen) + make_rd(test, xlen) elif (coverpoint == "cp_rs1"): - make_rs1(test, storecmd, xlen) + make_rs1(test, xlen) elif (coverpoint == "cp_rs2"): - make_rs2(test, storecmd, xlen) + make_rs2(test, xlen) elif (coverpoint == "cmp_rd_rs1"): - make_rd_rs1(test, storecmd, xlen) + make_rd_rs1(test, xlen) elif (coverpoint == "cmp_rd_rs2"): - make_rd_rs2(test, storecmd, xlen) + make_rd_rs2(test, xlen) elif (coverpoint == "cmp_rd_rs1_rs2"): - make_rd_rs1_rs2(test, storecmd, xlen) + make_rd_rs1_rs2(test, xlen) elif (coverpoint == "cmp_rd_rs1_eq"): pass # duplicate of cmp_rd_rs1 elif (coverpoint == "cmp_rd_rs2_eq"): pass # duplicate of cmp_rd_rs2 elif (coverpoint == "cmp_rs1_rs2_eq"): - make_rs1_rs2(test, storecmd, xlen) + make_rs1_rs2(test, xlen) elif (coverpoint == "cp_rs1_maxvals"): - make_rs1_maxvals(test, storecmd, xlen) + make_rs1_maxvals(test, xlen) elif (coverpoint == "cp_rs2_maxvals"): - make_rs2_maxvals(test, storecmd, xlen) + make_rs2_maxvals(test, xlen) elif (coverpoint == "cp_rd_maxvals"): - make_rd_maxvals(test, storecmd, xlen) + make_rd_maxvals(test, xlen) elif (coverpoint == "cmp_rd_rs1_eqval"): - make_rd_rs1_eqval(test, storecmd, xlen) + make_rd_rs1_eqval(test, xlen) elif (coverpoint == "cmp_rd_rs2_eqval"): - make_rd_rs2_eqval(test, storecmd, xlen) + make_rd_rs2_eqval(test, xlen) elif (coverpoint == "cmp_rs1_rs2_eqval"): - make_rs1_rs2_eqval(test, storecmd, xlen) + make_rs1_rs2_eqval(test, xlen) elif (coverpoint == "cp_rs1_sign"): - make_rs1_sign(test, storecmd, xlen) + make_rs1_sign(test, xlen) elif (coverpoint == "cp_rs2_sign"): - make_rs2_sign(test, storecmd, xlen) + make_rs2_sign(test, xlen) elif (coverpoint == "cp_rd_sign"): pass #TODO hope already covered by rd_maxvals elif (coverpoint == "cr_rs1_rs2"): - make_cr_rs1_rs2_sign(test, storecmd, xlen) + make_cr_rs1_rs2_sign(test, xlen) + elif (coverpoint == "cp_gpr_hazard"): + make_cp_gpr_hazard(test, xlen) elif (coverpoint == "cp_rs1_toggle"): pass #TODO toggle not needed and seems to be covered by other things elif (coverpoint == "cp_rs2_toggle"): pass #TODO toggle not needed and seems to be covered by other things elif (coverpoint == "cp_rd_toggle"): pass #TODO toggle not needed and seems to be covered by other things - elif (coverpoint == "cp_gpr_hazard"): - pass #TODO not yet implemented elif (coverpoint == "cp_imm_sign"): pass #TODO elif (coverpoint == "cr_rs1_imm"): @@ -355,8 +390,8 @@ for xlen in xlens: #if (test not in rtests): # exit("Error: %s not implemented yet" % test) #else: - # write_rtype_arith_vectors(test, storecmd, xlen) - write_tests(coverpoints[test], test, storecmd, xlen) + # write_rtype_arith_vectors(test, xlen) + write_tests(coverpoints[test], test, xlen) # print footer line = "\n.EQU NUMTESTS," + str(1) + "\n\n" From da502d2d5af4b04808cee8db73981284c254c873 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Sun, 21 Jul 2024 19:47:00 -0700 Subject: [PATCH 097/163] Fixed makefile log typo --- sim/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/sim/Makefile b/sim/Makefile index 5635431ff..891ccb213 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -91,6 +91,7 @@ combine_functcov: cd ${SIM}/questa/fcov && rm -rf * cd ${SIM}/questa/fcov_ucdb && rm -rf * wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf --fcov > ${SIM}/questa/fcov_logs/add.log 2>&1 + wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf --fcov > ${SIM}/questa/fcov_logs/and.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 From e949c9cfba1fe47de6a9fd5558a1b3f5740feebf Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Sun, 21 Jul 2024 19:47:23 -0700 Subject: [PATCH 098/163] Removed more obsolete imperas scripts --- sim/questa/run-imperas-linux.sh | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100755 sim/questa/run-imperas-linux.sh diff --git a/sim/questa/run-imperas-linux.sh b/sim/questa/run-imperas-linux.sh deleted file mode 100755 index aebf6b9d0..000000000 --- a/sim/questa/run-imperas-linux.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -#export RISCV=/scratch/moore/RISCV - -export IMPERAS_TOOLS=$(pwd)/imperas.ic -export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=100" -#export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=10500000" -#export OTHERFLAGS="" - -vsim -do "do wally.do buildroot buildroot testbench --lockstep +acc -GDEBUG=1" From e91d2c8b1457efbcceb0efd769a850b9b5422ba0 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Mon, 22 Jul 2024 01:19:10 -0500 Subject: [PATCH 099/163] Corrected the CRC7 code with the right sequence of instructions. --- fpga/zsbl/sd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 4ffb53d67..8781dd5c3 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,12 +1,15 @@ #include "sd.h" #include "spi.h" +// Parallel byte update CRC7-CCITT algorithm. +// The result is the CRC7 result, left shifted over by 1 +// which is perfect, since we append a 1 at the end anyway uint8_t crc7(uint8_t prev, uint8_t in) { // CRC polynomial 0x89 - uint8_t remainder = prev & in; + uint8_t remainder = prev ^ in; remainder ^= (remainder >> 4) ^ (remainder >> 7); - remainder ^= remainder << 4; - return remainder & 0x7f; + remainder = (remainder << 1) ^ (remainder << 4); + return remainder & 0xff; } uint16_t crc16(uint16_t crc, uint8_t data) { From c4400dfeb01e2d7f794506ba8d5aceb3e613e858 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 22 Jul 2024 08:45:08 -0700 Subject: [PATCH 100/163] Fixed WARL bug on MTVEC/STVEC alignment to 64 in vectored mode --- src/privileged/csrm.sv | 4 +++- src/privileged/csrs.sv | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index a964de2ea..f86b3f6d6 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -57,6 +57,7 @@ module csrm import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic [P.XLEN-1:0] MENVCFGH_REGW; + logic [P.XLEN-1:0] TVECWriteValM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; @@ -152,7 +153,8 @@ module csrm import cvw::*; #(parameter cvw_t P) ( assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID | CSRAdrM == MCONFIGPTR); // CSRs - flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); + assign TVECWriteValM = CSRWriteValM[0] ? {CSRWriteValM[P.XLEN-1:6], 6'b000001} : {CSRWriteValM[P.XLEN-1:2], 2'b00}; + flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, TVECWriteValM, MTVEC_REGW); if (P.S_SUPPORTED) begin:deleg // DELEG registers should exist flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW); flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index ebd468ad6..4797f800b 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -78,6 +78,7 @@ module csrs import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; logic [P.XLEN-1:0] SENVCFG_WriteValM; + logic [P.XLEN-1:0] TVECWriteValM; logic [63:0] STIMECMP_REGW; @@ -100,7 +101,8 @@ module csrs import cvw::*; #(parameter cvw_t P) ( assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32); // CSRs - flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); + assign TVECWriteValM = CSRWriteValM[0] ? {CSRWriteValM[P.XLEN-1:6], 6'b000001} : {CSRWriteValM[P.XLEN-1:2], 2'b00}; // could share this with MTVEC, but reduces to 4-bit AND to mask bits [5:2] + flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, TVECWriteValM, STVEC_REGW); flopenr #(P.XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(P.XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(P.XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(P.XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW); From 757cc8a5f7b39e8e336a8016356a5b252adaa502 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 22 Jul 2024 08:49:54 -0700 Subject: [PATCH 101/163] Added QuestaFunctCoverage to merge functional coverage reports --- bin/regression-wally | 54 ++++++++++++++++++++++++++++++++++++-------- sim/Makefile | 7 ++++++ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/bin/regression-wally b/bin/regression-wally index 8d67e387b..21f30c9c0 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -282,6 +282,22 @@ def addTests(tests, sim): grepfile = grepfile) configs.append(tc) +def addLockstepTestsByDir(dir, config, sim): + sim_logdir = WALLY+ "/sim/" + sim + "/logs/" + cmdPrefix="wsim --sim " + sim + " " + coverStr + " " + config + for file in os.listdir(dir): + if file.endswith(".elf"): + fullfile = os.path.join(dir, file) + sim_log = sim_logdir + config + "_" + file + grepstring = "" + tc = TestCase( + name=file, + variant=config, + cmd=cmdPrefix + " " + fullfile + " > " + sim_log, + grepstr="Mismatches : 0", + grepfile = sim_log) + configs.append(tc) + def search_log_for_text(text, grepfile): """Search through the given log file for text, returning True if it is found or False if it is not""" grepwarn = "grep -H Warning: " + grepfile @@ -332,14 +348,15 @@ args = parser.parse_args() if (args.nightly): nightMode = "--nightly"; -# sims = [defaultsim] # uncomment to use only the default simulator - sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators + sims = ["questa", "verilator", "vcs"] # exercise all simulators; can omit a sim if no license is available else: nightMode = "" sims = [defaultsim] if (args.ccov): # only run RV64GC tests in coverage mode coverStr = '--ccov' +elif (args.fcov): # only run RV64GC tests in lockstep in coverage mode + coverStr = '--fcov' else: coverStr = '' @@ -362,10 +379,20 @@ if (args.buildroot): addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight if (args.ccov): # only run RV64GC tests on Questa in code coverage mode - addTests(tests64gc_nofp, "questa") + addTests(tests64gc_nofp, coveragesim) if (args.fp): - addTests(tests64gc_fp, "questa") -else: + addTests(tests64gc_fp, coveragesim) +elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode + addLockstepTestsByDir(WALLY+"/tests/functcov/rv64/I", "rv64gc", coveragesim) + #sim_log = WALLY + "/sim/questa/logs/fcov.log" + #tc = TestCase( + # name="lockstep_functcov", + # variant="rv64gc", + # cmd="iterelf " + WALLY + "/tests/functcov/rv64/I > " + sim_log, + # grepstr="SUCCESS! All tests ran without failures", + # grepfile = sim_log) + #configs.append(tc) +else: for sim in sims: if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one addTests(tests_buildrootshort, sim) @@ -375,7 +402,6 @@ else: # run derivative configurations and lockstep tests in nightly regression if (args.nightly): - addTests(derivconfigtests, defaultsim) sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log" tc = TestCase( name="lockstep_coverage", @@ -393,6 +419,7 @@ if (args.nightly): grepstr="SUCCESS! All tests ran without failures", grepfile = sim_log) configs.append(tc) + addTests(derivconfigtests, defaultsim) # testfloat tests if (args.testfloat): # for testfloat alone, just run testfloat tests @@ -474,16 +501,23 @@ def main(): if args.ccov: TIMEOUT_DUR = 20*60 # seconds os.system('rm -f questa/cov/*.ucdb') - elif args.nightly in sys.argv: + elif args.fcov: + TIMEOUT_DUR = 1*60 + os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*') + elif args.nightly: TIMEOUT_DUR = 60*1440 # 1 day - elif args.testfloat in sys.argv: + elif args.testfloat: TIMEOUT_DUR = 30*60 # seconds else: TIMEOUT_DUR = 10*60 # seconds # Scale the number of concurrent processes to the number of test cases, but # max out at a limited number of concurrent processes to not overwhelm the system - with Pool(processes=min(len(configs),multiprocessing.cpu_count())) as pool: + if (args.lockstep or args.fcov): + ImperasDVLicenseCount = 8 # limit number of concurrent processes to avoid overloading ImperasDV licenses + else: + ImperasDVLicenseCount = 10000 # effectively no license limit for non-lockstep tests + with Pool(processes=min(len(configs),multiprocessing.cpu_count(), ImperasDVLicenseCount)) as pool: num_fail = 0 results = {} for config in configs: @@ -498,6 +532,8 @@ def main(): # Coverage report if args.ccov: os.system('make QuestaCodeCoverage') + if args.fcov: + os.system('make QuestaFunctCoverage') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/sim/Makefile b/sim/Makefile index 891ccb213..1197dfc2e 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -30,6 +30,13 @@ QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb # vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt vcover report -details -threshH 100 -html questa/ucdb/cov.ucdb +QuestaFunctCoverage: ${SIM}/questa/fcov_ucdb/rv64gc_WALLY-COV-add.elf.ucdb + vcover merge -out ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_WALLY-COV-add.elf.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_WALLY*.ucdb -logfile ${SIM}/questa/fcov_logs/log + vcover report -details -html ${SIM}/questa/fcov_ucdb/fcov.ucdb + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg > ${SIM}/questa/fcov/fcov.log + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -testdetails -cvg > ${SIM}/questa/fcov/fcov.testdetails.log + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/fcov/fcov.summary.log + grep "TOTAL COVERGROUP COVERAGE" ${SIM}/questa/fcov/fcov.log imperasdv_cov: touch ${SIM}/seed0.txt From 24609f0b7f5f89ede712adcc7a38a1ee83c03360 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 22 Jul 2024 10:51:13 -0500 Subject: [PATCH 102/163] Now have configurations to switch between supporting RVVI over ethernet. --- config/derivlist.txt | 2 +- fpga/constraints/small-debug-rvvi.xdc | 83 +++++++++++++++++++++++++++ fpga/constraints/small-debug.xdc | 56 ++++++++++++------ fpga/src/fpgaTopArtyA7.sv | 9 +-- 4 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 fpga/constraints/small-debug-rvvi.xdc diff --git a/config/derivlist.txt b/config/derivlist.txt index 9535e9833..177cac54f 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -56,7 +56,7 @@ EXT_MEM_RANGE 64'h0FFFFFFF SDC_SUPPORTED 1 PLIC_SDC_ID 32'd20 BPRED_SIZE 32'd12 -RVVI_SYNTH_SUPPORTED 1 +RVVI_SYNTH_SUPPORTED 0 RVVI_INIT_TIME_OUT 32'd100000000 RVVI_PACKET_DELAY 32'd350 diff --git a/fpga/constraints/small-debug-rvvi.xdc b/fpga/constraints/small-debug-rvvi.xdc new file mode 100644 index 000000000..f8ebbfe0d --- /dev/null +++ b/fpga/constraints/small-debug-rvvi.xdc @@ -0,0 +1,83 @@ +create_debug_core u_ila_0 ila +set_property C_DATA_DEPTH 8192 [get_debug_cores u_ila_0] +set_property C_TRIGIN_EN true [get_debug_cores u_ila_0] +set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] +set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] +set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0] +set_property C_EN_STRG_QUAL true [get_debug_cores u_ila_0 ] +set_property C_ADV_TRIGGER true [get_debug_cores u_ila_0 ] +set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0 ] +set_property ALL_PROBE_SAME_MU_CNT 4 [get_debug_cores u_ila_0 ] +create_debug_port u_ila_0 trig_in +create_debug_port u_ila_0 trig_in_ack +#set_property port_width 1 [get_debug_ports u_ila_0/trig_in] +#set_property port_width 1 [get_debug_ports u_ila_0/trig_in_ack] +#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/trig_in] +connect_debug_port u_ila_0/trig_in [get_nets IlaTrigger] +#connect_debug_port u_ila_0/trig_in_ack [get_nets IlaTriggerAck] +connect_debug_port u_ila_0/clk [get_nets CPUCLK] + +set_property port_width 32 [get_debug_ports u_ila_0/probe0] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] +connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe1] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] +connect_debug_port u_ila_0/probe1 [get_nets [list rvvi_synth/RvviAxiWlast ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe2] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] +connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe3] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] +connect_debug_port u_ila_0/probe3 [get_nets [list {rvvi_synth/RvviAxiRlast}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe4] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] +connect_debug_port u_ila_0/probe4 [get_nets [list {rvvi_synth/RvviAxiRvalid}]] + +create_debug_port u_ila_0 probe +set_property port_width 4 [get_debug_ports u_ila_0/probe5] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] +connect_debug_port u_ila_0/probe5 [get_nets [list {rvvi_synth/packetizer/CurrState[0]} {rvvi_synth/packetizer/CurrState[1]} {rvvi_synth/packetizer/CurrState[2]} {rvvi_synth/packetizer/CurrState[3]}]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe6] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] +connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe7] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] +connect_debug_port u_ila_0/probe7 [get_nets [list {rvvi_synth/RvviAxiWvalid}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe8] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] +connect_debug_port u_ila_0/probe8 [get_nets [list {RVVIStall}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe9] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] +connect_debug_port u_ila_0/probe9 [get_nets [list {rvvi_synth/valid}]] + +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe10] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] +connect_debug_port u_ila_0/probe10 [get_nets [list {rvvi_synth/RvviAxiWready}]] + +create_debug_port u_ila_0 probe +set_property port_width 3 [get_debug_ports u_ila_0/probe11] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] +connect_debug_port u_ila_0/probe11 [get_nets [list {rvvi_synth/triggergen/CurrState[0]} {rvvi_synth/triggergen/CurrState[1]} {rvvi_synth/triggergen/CurrState[2]}]] + + +# the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. +#connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] +connect_debug_port dbg_hub/clk [get_nets CPUCLK] + diff --git a/fpga/constraints/small-debug.xdc b/fpga/constraints/small-debug.xdc index 6fef2ba79..b73581ab7 100644 --- a/fpga/constraints/small-debug.xdc +++ b/fpga/constraints/small-debug.xdc @@ -1,45 +1,63 @@ create_debug_core u_ila_0 ila -set_property C_DATA_DEPTH 8192 [get_debug_cores u_ila_0] -set_property C_TRIGIN_EN true [get_debug_cores u_ila_0] + + + + +set_property C_DATA_DEPTH 1024 [get_debug_cores u_ila_0] +set_property C_TRIGIN_EN false [get_debug_cores u_ila_0] set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] +set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0] set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] +set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0] set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0] +set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0] +startgroup set_property C_EN_STRG_QUAL true [get_debug_cores u_ila_0 ] set_property C_ADV_TRIGGER true [get_debug_cores u_ila_0 ] set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0 ] set_property ALL_PROBE_SAME_MU_CNT 4 [get_debug_cores u_ila_0 ] -create_debug_port u_ila_0 trig_in -create_debug_port u_ila_0 trig_in_ack -#set_property port_width 1 [get_debug_ports u_ila_0/trig_in] -#set_property port_width 1 [get_debug_ports u_ila_0/trig_in_ack] -#set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/trig_in] -connect_debug_port u_ila_0/trig_in [get_nets IlaTrigger] -#connect_debug_port u_ila_0/trig_in_ack [get_nets IlaTriggerAck] +endgroup connect_debug_port u_ila_0/clk [get_nets CPUCLK] -set_property port_width 32 [get_debug_ports u_ila_0/probe0] +set_property port_width 64 [get_debug_ports u_ila_0/probe0] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] -connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] - +connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe1] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] -connect_debug_port u_ila_0/probe1 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] +connect_debug_port u_ila_0/probe1 [get_nets [list wallypipelinedsoc/core/TrapM ]] create_debug_port u_ila_0 probe -set_property port_width 64 [get_debug_ports u_ila_0/probe2] +set_property port_width 1 [get_debug_ports u_ila_0/probe2] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] -connect_debug_port u_ila_0/probe2 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] - +connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe3] +set_property port_width 32 [get_debug_ports u_ila_0/probe3] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] -connect_debug_port u_ila_0/probe3 [get_nets [list {RVVIStall}]] +connect_debug_port u_ila_0/probe3 [get_nets [list {wallypipelinedsoc/core/InstrM[0]} {wallypipelinedsoc/core/InstrM[1]} {wallypipelinedsoc/core/InstrM[2]} {wallypipelinedsoc/core/InstrM[3]} {wallypipelinedsoc/core/InstrM[4]} {wallypipelinedsoc/core/InstrM[5]} {wallypipelinedsoc/core/InstrM[6]} {wallypipelinedsoc/core/InstrM[7]} {wallypipelinedsoc/core/InstrM[8]} {wallypipelinedsoc/core/InstrM[9]} {wallypipelinedsoc/core/InstrM[10]} {wallypipelinedsoc/core/InstrM[11]} {wallypipelinedsoc/core/InstrM[12]} {wallypipelinedsoc/core/InstrM[13]} {wallypipelinedsoc/core/InstrM[14]} {wallypipelinedsoc/core/InstrM[15]} {wallypipelinedsoc/core/InstrM[16]} {wallypipelinedsoc/core/InstrM[17]} {wallypipelinedsoc/core/InstrM[18]} {wallypipelinedsoc/core/InstrM[19]} {wallypipelinedsoc/core/InstrM[20]} {wallypipelinedsoc/core/InstrM[21]} {wallypipelinedsoc/core/InstrM[22]} {wallypipelinedsoc/core/InstrM[23]} {wallypipelinedsoc/core/InstrM[24]} {wallypipelinedsoc/core/InstrM[25]} {wallypipelinedsoc/core/InstrM[26]} {wallypipelinedsoc/core/InstrM[27]} {wallypipelinedsoc/core/InstrM[28]} {wallypipelinedsoc/core/InstrM[29]} {wallypipelinedsoc/core/InstrM[30]} {wallypipelinedsoc/core/InstrM[31]} ]] +create_debug_port u_ila_0 probe +set_property port_width 2 [get_debug_ports u_ila_0/probe4] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] +connect_debug_port u_ila_0/probe4 [get_nets [list {wallypipelinedsoc/core/lsu/MemRWM[0]} {wallypipelinedsoc/core/lsu/MemRWM[1]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe5] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] +connect_debug_port u_ila_0/probe5 [get_nets [list {wallypipelinedsoc/core/lsu/IEUAdrM[0]} {wallypipelinedsoc/core/lsu/IEUAdrM[1]} {wallypipelinedsoc/core/lsu/IEUAdrM[2]} {wallypipelinedsoc/core/lsu/IEUAdrM[3]} {wallypipelinedsoc/core/lsu/IEUAdrM[4]} {wallypipelinedsoc/core/lsu/IEUAdrM[5]} {wallypipelinedsoc/core/lsu/IEUAdrM[6]} {wallypipelinedsoc/core/lsu/IEUAdrM[7]} {wallypipelinedsoc/core/lsu/IEUAdrM[8]} {wallypipelinedsoc/core/lsu/IEUAdrM[9]} {wallypipelinedsoc/core/lsu/IEUAdrM[10]} {wallypipelinedsoc/core/lsu/IEUAdrM[11]} {wallypipelinedsoc/core/lsu/IEUAdrM[12]} {wallypipelinedsoc/core/lsu/IEUAdrM[13]} {wallypipelinedsoc/core/lsu/IEUAdrM[14]} {wallypipelinedsoc/core/lsu/IEUAdrM[15]} {wallypipelinedsoc/core/lsu/IEUAdrM[16]} {wallypipelinedsoc/core/lsu/IEUAdrM[17]} {wallypipelinedsoc/core/lsu/IEUAdrM[18]} {wallypipelinedsoc/core/lsu/IEUAdrM[19]} {wallypipelinedsoc/core/lsu/IEUAdrM[20]} {wallypipelinedsoc/core/lsu/IEUAdrM[21]} {wallypipelinedsoc/core/lsu/IEUAdrM[22]} {wallypipelinedsoc/core/lsu/IEUAdrM[23]} {wallypipelinedsoc/core/lsu/IEUAdrM[24]} {wallypipelinedsoc/core/lsu/IEUAdrM[25]} {wallypipelinedsoc/core/lsu/IEUAdrM[26]} {wallypipelinedsoc/core/lsu/IEUAdrM[27]} {wallypipelinedsoc/core/lsu/IEUAdrM[28]} {wallypipelinedsoc/core/lsu/IEUAdrM[29]} {wallypipelinedsoc/core/lsu/IEUAdrM[30]} {wallypipelinedsoc/core/lsu/IEUAdrM[31]} {wallypipelinedsoc/core/lsu/IEUAdrM[32]} {wallypipelinedsoc/core/lsu/IEUAdrM[33]} {wallypipelinedsoc/core/lsu/IEUAdrM[34]} {wallypipelinedsoc/core/lsu/IEUAdrM[35]} {wallypipelinedsoc/core/lsu/IEUAdrM[36]} {wallypipelinedsoc/core/lsu/IEUAdrM[37]} {wallypipelinedsoc/core/lsu/IEUAdrM[38]} {wallypipelinedsoc/core/lsu/IEUAdrM[39]} {wallypipelinedsoc/core/lsu/IEUAdrM[40]} {wallypipelinedsoc/core/lsu/IEUAdrM[41]} {wallypipelinedsoc/core/lsu/IEUAdrM[42]} {wallypipelinedsoc/core/lsu/IEUAdrM[43]} {wallypipelinedsoc/core/lsu/IEUAdrM[44]} {wallypipelinedsoc/core/lsu/IEUAdrM[45]} {wallypipelinedsoc/core/lsu/IEUAdrM[46]} {wallypipelinedsoc/core/lsu/IEUAdrM[47]} {wallypipelinedsoc/core/lsu/IEUAdrM[48]} {wallypipelinedsoc/core/lsu/IEUAdrM[49]} {wallypipelinedsoc/core/lsu/IEUAdrM[50]} {wallypipelinedsoc/core/lsu/IEUAdrM[51]} {wallypipelinedsoc/core/lsu/IEUAdrM[52]} {wallypipelinedsoc/core/lsu/IEUAdrM[53]} {wallypipelinedsoc/core/lsu/IEUAdrM[54]} {wallypipelinedsoc/core/lsu/IEUAdrM[55]} {wallypipelinedsoc/core/lsu/IEUAdrM[56]} {wallypipelinedsoc/core/lsu/IEUAdrM[57]} {wallypipelinedsoc/core/lsu/IEUAdrM[58]} {wallypipelinedsoc/core/lsu/IEUAdrM[59]} {wallypipelinedsoc/core/lsu/IEUAdrM[60]} {wallypipelinedsoc/core/lsu/IEUAdrM[61]} {wallypipelinedsoc/core/lsu/IEUAdrM[62]} {wallypipelinedsoc/core/lsu/IEUAdrM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe6] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] +connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/lsu/ReadDataM[0]} {wallypipelinedsoc/core/lsu/ReadDataM[1]} {wallypipelinedsoc/core/lsu/ReadDataM[2]} {wallypipelinedsoc/core/lsu/ReadDataM[3]} {wallypipelinedsoc/core/lsu/ReadDataM[4]} {wallypipelinedsoc/core/lsu/ReadDataM[5]} {wallypipelinedsoc/core/lsu/ReadDataM[6]} {wallypipelinedsoc/core/lsu/ReadDataM[7]} {wallypipelinedsoc/core/lsu/ReadDataM[8]} {wallypipelinedsoc/core/lsu/ReadDataM[9]} {wallypipelinedsoc/core/lsu/ReadDataM[10]} {wallypipelinedsoc/core/lsu/ReadDataM[11]} {wallypipelinedsoc/core/lsu/ReadDataM[12]} {wallypipelinedsoc/core/lsu/ReadDataM[13]} {wallypipelinedsoc/core/lsu/ReadDataM[14]} {wallypipelinedsoc/core/lsu/ReadDataM[15]} {wallypipelinedsoc/core/lsu/ReadDataM[16]} {wallypipelinedsoc/core/lsu/ReadDataM[17]} {wallypipelinedsoc/core/lsu/ReadDataM[18]} {wallypipelinedsoc/core/lsu/ReadDataM[19]} {wallypipelinedsoc/core/lsu/ReadDataM[20]} {wallypipelinedsoc/core/lsu/ReadDataM[21]} {wallypipelinedsoc/core/lsu/ReadDataM[22]} {wallypipelinedsoc/core/lsu/ReadDataM[23]} {wallypipelinedsoc/core/lsu/ReadDataM[24]} {wallypipelinedsoc/core/lsu/ReadDataM[25]} {wallypipelinedsoc/core/lsu/ReadDataM[26]} {wallypipelinedsoc/core/lsu/ReadDataM[27]} {wallypipelinedsoc/core/lsu/ReadDataM[28]} {wallypipelinedsoc/core/lsu/ReadDataM[29]} {wallypipelinedsoc/core/lsu/ReadDataM[30]} {wallypipelinedsoc/core/lsu/ReadDataM[31]} {wallypipelinedsoc/core/lsu/ReadDataM[32]} {wallypipelinedsoc/core/lsu/ReadDataM[33]} {wallypipelinedsoc/core/lsu/ReadDataM[34]} {wallypipelinedsoc/core/lsu/ReadDataM[35]} {wallypipelinedsoc/core/lsu/ReadDataM[36]} {wallypipelinedsoc/core/lsu/ReadDataM[37]} {wallypipelinedsoc/core/lsu/ReadDataM[38]} {wallypipelinedsoc/core/lsu/ReadDataM[39]} {wallypipelinedsoc/core/lsu/ReadDataM[40]} {wallypipelinedsoc/core/lsu/ReadDataM[41]} {wallypipelinedsoc/core/lsu/ReadDataM[42]} {wallypipelinedsoc/core/lsu/ReadDataM[43]} {wallypipelinedsoc/core/lsu/ReadDataM[44]} {wallypipelinedsoc/core/lsu/ReadDataM[45]} {wallypipelinedsoc/core/lsu/ReadDataM[46]} {wallypipelinedsoc/core/lsu/ReadDataM[47]} {wallypipelinedsoc/core/lsu/ReadDataM[48]} {wallypipelinedsoc/core/lsu/ReadDataM[49]} {wallypipelinedsoc/core/lsu/ReadDataM[50]} {wallypipelinedsoc/core/lsu/ReadDataM[51]} {wallypipelinedsoc/core/lsu/ReadDataM[52]} {wallypipelinedsoc/core/lsu/ReadDataM[53]} {wallypipelinedsoc/core/lsu/ReadDataM[54]} {wallypipelinedsoc/core/lsu/ReadDataM[55]} {wallypipelinedsoc/core/lsu/ReadDataM[56]} {wallypipelinedsoc/core/lsu/ReadDataM[57]} {wallypipelinedsoc/core/lsu/ReadDataM[58]} {wallypipelinedsoc/core/lsu/ReadDataM[59]} {wallypipelinedsoc/core/lsu/ReadDataM[60]} {wallypipelinedsoc/core/lsu/ReadDataM[61]} {wallypipelinedsoc/core/lsu/ReadDataM[62]} {wallypipelinedsoc/core/lsu/ReadDataM[63]} ]] + +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe7] +set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] +connect_debug_port u_ila_0/probe7 [get_nets [list {wallypipelinedsoc/core/lsu/WriteDataM[0]} {wallypipelinedsoc/core/lsu/WriteDataM[1]} {wallypipelinedsoc/core/lsu/WriteDataM[2]} {wallypipelinedsoc/core/lsu/WriteDataM[3]} {wallypipelinedsoc/core/lsu/WriteDataM[4]} {wallypipelinedsoc/core/lsu/WriteDataM[5]} {wallypipelinedsoc/core/lsu/WriteDataM[6]} {wallypipelinedsoc/core/lsu/WriteDataM[7]} {wallypipelinedsoc/core/lsu/WriteDataM[8]} {wallypipelinedsoc/core/lsu/WriteDataM[9]} {wallypipelinedsoc/core/lsu/WriteDataM[10]} {wallypipelinedsoc/core/lsu/WriteDataM[11]} {wallypipelinedsoc/core/lsu/WriteDataM[12]} {wallypipelinedsoc/core/lsu/WriteDataM[13]} {wallypipelinedsoc/core/lsu/WriteDataM[14]} {wallypipelinedsoc/core/lsu/WriteDataM[15]} {wallypipelinedsoc/core/lsu/WriteDataM[16]} {wallypipelinedsoc/core/lsu/WriteDataM[17]} {wallypipelinedsoc/core/lsu/WriteDataM[18]} {wallypipelinedsoc/core/lsu/WriteDataM[19]} {wallypipelinedsoc/core/lsu/WriteDataM[20]} {wallypipelinedsoc/core/lsu/WriteDataM[21]} {wallypipelinedsoc/core/lsu/WriteDataM[22]} {wallypipelinedsoc/core/lsu/WriteDataM[23]} {wallypipelinedsoc/core/lsu/WriteDataM[24]} {wallypipelinedsoc/core/lsu/WriteDataM[25]} {wallypipelinedsoc/core/lsu/WriteDataM[26]} {wallypipelinedsoc/core/lsu/WriteDataM[27]} {wallypipelinedsoc/core/lsu/WriteDataM[28]} {wallypipelinedsoc/core/lsu/WriteDataM[29]} {wallypipelinedsoc/core/lsu/WriteDataM[30]} {wallypipelinedsoc/core/lsu/WriteDataM[31]} {wallypipelinedsoc/core/lsu/WriteDataM[32]} {wallypipelinedsoc/core/lsu/WriteDataM[33]} {wallypipelinedsoc/core/lsu/WriteDataM[34]} {wallypipelinedsoc/core/lsu/WriteDataM[35]} {wallypipelinedsoc/core/lsu/WriteDataM[36]} {wallypipelinedsoc/core/lsu/WriteDataM[37]} {wallypipelinedsoc/core/lsu/WriteDataM[38]} {wallypipelinedsoc/core/lsu/WriteDataM[39]} {wallypipelinedsoc/core/lsu/WriteDataM[40]} {wallypipelinedsoc/core/lsu/WriteDataM[41]} {wallypipelinedsoc/core/lsu/WriteDataM[42]} {wallypipelinedsoc/core/lsu/WriteDataM[43]} {wallypipelinedsoc/core/lsu/WriteDataM[44]} {wallypipelinedsoc/core/lsu/WriteDataM[45]} {wallypipelinedsoc/core/lsu/WriteDataM[46]} {wallypipelinedsoc/core/lsu/WriteDataM[47]} {wallypipelinedsoc/core/lsu/WriteDataM[48]} {wallypipelinedsoc/core/lsu/WriteDataM[49]} {wallypipelinedsoc/core/lsu/WriteDataM[50]} {wallypipelinedsoc/core/lsu/WriteDataM[51]} {wallypipelinedsoc/core/lsu/WriteDataM[52]} {wallypipelinedsoc/core/lsu/WriteDataM[53]} {wallypipelinedsoc/core/lsu/WriteDataM[54]} {wallypipelinedsoc/core/lsu/WriteDataM[55]} {wallypipelinedsoc/core/lsu/WriteDataM[56]} {wallypipelinedsoc/core/lsu/WriteDataM[57]} {wallypipelinedsoc/core/lsu/WriteDataM[58]} {wallypipelinedsoc/core/lsu/WriteDataM[59]} {wallypipelinedsoc/core/lsu/WriteDataM[60]} {wallypipelinedsoc/core/lsu/WriteDataM[61]} {wallypipelinedsoc/core/lsu/WriteDataM[62]} {wallypipelinedsoc/core/lsu/WriteDataM[63]} ]] # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] connect_debug_port dbg_hub/clk [get_nets CPUCLK] - diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 48a02fb89..4fe8ce183 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -1115,6 +1115,9 @@ module fpgaTop .init_calib_complete(c0_init_calib_complete), .device_temp(device_temp)); + (* mark_debug = "true" *) logic IlaTrigger; + + if(P.RVVI_SYNTH_SUPPORTED) begin : rvvi_synth localparam MAX_CSRS = 3; localparam TOTAL_CSRS = 36; @@ -1212,9 +1215,6 @@ module fpgaTop logic [3:0] RvviAxiRstrb; logic RvviAxiRlast; logic RvviAxiRvalid; - (* mark_debug = "true" *) logic IlaTrigger; - - logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; @@ -1246,11 +1246,12 @@ module fpgaTop triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger); end else begin // if (P.RVVI_SYNTH_SUPPORTED) + assign IlaTrigger = '0; assign RVVIStall = '0; end //assign phy_reset_n = ~bus_struct_reset; assign phy_reset_n = ~1'b0; - + endmodule From 040b359813a7aa471985f2e55735af77b8845b47 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 22 Jul 2024 08:52:19 -0700 Subject: [PATCH 103/163] Added more RV64I coverage generation --- sim/questa/wally.do | 13 ++++---- tests/testgen/covergen.py | 63 ++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/sim/questa/wally.do b/sim/questa/wally.do index e5c85b92e..c7cba4925 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -122,13 +122,14 @@ if {$FunctCoverageIndex >= 0} { set FCdefineINCLUDE_TRACE2COV "+define+INCLUDE_TRACE2COV" set FCdefineCOVER_BASE_RV64I "+define+COVER_BASE_RV64I" set FCdefineCOVER_LEVEL_DV_PR_EXT "+define+COVER_LEVEL_DV_PR_EXT" + # Uncomment various cover statements below to control which extensions get functional coverage set FCdefineCOVER_RV64I "+define+COVER_RV64I" - set FCdefineCOVER_RV64M "+define+COVER_RV64M" - set FCdefineCOVER_RV64A "+define+COVER_RV64A" - set FCdefineCOVER_RV64F "+define+COVER_RV64F" - set FCdefineCOVER_RV64D "+define+COVER_RV64D" - set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" - set FCdefineCOVER_RV64C "+define+COVER_RV64C" + #set FCdefineCOVER_RV64M "+define+COVER_RV64M" + #set FCdefineCOVER_RV64A "+define+COVER_RV64A" + #set FCdefineCOVER_RV64F "+define+COVER_RV64F" + #set FCdefineCOVER_RV64D "+define+COVER_RV64D" + #set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" + #set FCdefineCOVER_RV64C "+define+COVER_RV64C" set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" set FCTRACE2COV "+TRACE2COV_ENABLE=1" set FCdefineIDV_TRACE2COV "+IDV_TRACE2COV=1" diff --git a/tests/testgen/covergen.py b/tests/testgen/covergen.py index 0f7bb0d4e..06cf1bb83 100755 --- a/tests/testgen/covergen.py +++ b/tests/testgen/covergen.py @@ -31,10 +31,8 @@ def signedImm12(imm): imm = imm - 0x1000 return str(imm) -def signedImm20(imm): +def unsignedImm20(imm): imm = imm % pow(2, 20) - if (imm & 0x80000): - imm = imm - 0x100000 return str(imm) def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen): @@ -43,7 +41,7 @@ def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen rs1val = rs1val + 2**xlen if (rs2val < 0): rs2val = rs2val + 2**xlen - lines = lines + "li x" + str(rd) + ", " + formatstr.format(rdval) + " # initialize rd to a random value that should get changed\n" + lines = lines + "li x" + str(rd) + ", " + formatstr.format(rdval) + " # initialize rd to a random value that should get changed; helps covering rd_toggle\n" if (test in rtype): lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" @@ -55,15 +53,16 @@ def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n" elif (test in loaditype):#["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] - lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" - lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # add immediate to lower part of rs1\n" - lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" - elif (test in stypes):#["sb", "sh", "sw", "sd"] + pass + #lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" + #lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # add immediate to lower part of rs1\n" + #lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" + elif (test in stype):#["sb", "sh", "sw", "sd"] #lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" #lines = lines + test + " x" + str(rs2) + ", " "0(x" + str(rs1) + ") # perform operation \n" #print("Error: %s type not implemented yet" % test) pass - elif (test in btypes):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] + elif (test in btype):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] if (randint(1,100) > 50): rs1val = rs2val lines = lines + "# same values in both registers\n" @@ -75,6 +74,18 @@ def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen lines = lines + "some_label_for_sb_types_" + str(immval) + ":\n" lines = lines + "addi x0, x2, 2\n" lines = lines + "nop\nnop\nnop\nnop\nnop\n" + elif (test in jtype):#["jal"] + lines = lines + "jal x" + str(rd) + ", 1f # perform operation\n" + lines = lines + "nop\n" + lines = lines + "1:\n" + elif (test in jalrtype):#["jalr"] + lines = lines + "la x" + str(rs1) + ", 1f\n" + lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # add immediate to lower part of rs1\n" + lines = lines + "jalr x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n" + lines = lines + "nop\n" + lines = lines + "1:\n" + elif (test in utype):#["lui", "auipc"] + lines = lines + test + " x" + str(rd) + ", " + unsignedImm20(immval) + " # perform operation\n" else: pass #print("Error: %s type not implemented yet" % test) @@ -229,6 +240,11 @@ def make_cr_rs1_rs2_sign(test, xlen): desc = "cr_rs1_rs2 (Test source rs1 = " + hex(rs1val) + " rs2 = " + hex(rs2val) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) +def make_imm_zero(test, xlen): + [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() + desc = "cp_imm_zero" + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, 0, rdval, test, xlen) + def write_tests(coverpoints, test, xlen): for coverpoint in coverpoints: if (coverpoint == "cp_asm_count"): @@ -280,7 +296,7 @@ def write_tests(coverpoints, test, xlen): elif (coverpoint == "cp_rd_toggle"): pass #TODO toggle not needed and seems to be covered by other things elif (coverpoint == "cp_imm_sign"): - pass #TODO + make_imm_zero(test, xlen) elif (coverpoint == "cr_rs1_imm"): pass #TODO (not if crosses are not needed) elif (coverpoint == "cp_imm_ones_zeros"): @@ -288,7 +304,7 @@ def write_tests(coverpoints, test, xlen): elif (coverpoint == "cp_mem_hazard"): pass #TODO elif (coverpoint == "cp_imm_zero"): - pass #TODO + make_imm_zero(test, xlen) elif (coverpoint == "cp_mem_unaligned"): pass #TODO elif (coverpoint == "cp_offset"): @@ -338,8 +354,11 @@ rtype = ["add", "sub", "sll", "slt", "sltu", "xor", "srl", "sra", "or", "and", loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] shiftitype = ["slli", "srli", "srai"] itype = ["addi", "slti", "sltiu", "xori", "ori", "andi"] -stypes = ["sb", "sh", "sw", "sd"] -btypes = ["beq", "bne", "blt", "bge", "bltu", "bgeu"] +stype = ["sb", "sh", "sw", "sd"] +btype = ["beq", "bne", "blt", "bge", "bltu", "bgeu"] +jtype = ["jal"] +jalrtype = ["jalr"] +utype = ["lui", "auipc"] # TODO: auipc missing, check whatelse is missing in ^these^ types coverpoints = getcovergroups(coverdefdir, coverfiles) @@ -362,12 +381,11 @@ for xlen in xlens: else: storecmd = "sd" wordsize = 8 + WALLY = os.environ.get('WALLY') + pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/" + cmd = "mkdir -p " + pathname + " ; rm -f " + pathname + "/*" # make directory and remove old tests in dir + os.system(cmd) for test in coverpoints.keys(): -# pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/" - WALLY = os.environ.get('WALLY') - pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/" - cmd = "mkdir -p " + pathname - os.system(cmd) basename = "WALLY-COV-" + test fname = pathname + "/" + basename + ".S" @@ -375,9 +393,9 @@ for xlen in xlens: f = open(fname, "w") line = "///////////////////////////////////////////\n" f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) + line="// "+fname+ "\n// " + author + "\n" + f.write(line) + line ="// Created " + str(datetime.now()) + "\n" f.write(line) # insert generic header @@ -401,9 +419,6 @@ for xlen in xlens: f.write(line) # Finish -# lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" -# lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) f.close() From 4c46315907b094190f3092d19f005942c8f620a7 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Mon, 22 Jul 2024 09:19:56 -0700 Subject: [PATCH 104/163] Fixed argument name in regression-wally --- bin/regression-wally | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/regression-wally b/bin/regression-wally index 21f30c9c0..5a374b2d9 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -513,7 +513,8 @@ def main(): # Scale the number of concurrent processes to the number of test cases, but # max out at a limited number of concurrent processes to not overwhelm the system - if (args.lockstep or args.fcov): + # right now fcov, ccov, nightly all use Imperas + if (args.ccov or args.fcov or args.nightly): ImperasDVLicenseCount = 8 # limit number of concurrent processes to avoid overloading ImperasDV licenses else: ImperasDVLicenseCount = 10000 # effectively no license limit for non-lockstep tests From 556c210e76158e69e3308f755f58134f1798de17 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 22 Jul 2024 12:19:37 -0500 Subject: [PATCH 105/163] Added option to use rvvi ila --- fpga/generator/wally.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index eff0a6cb9..9df775646 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -90,6 +90,7 @@ write_verilog -force -mode funcsim sim/syn-funcsim.v if {$board=="ArtyA7"} { source ../constraints/small-debug.xdc + #source ../constraints/small-debug-rvvi.xdc } else { # source ../constraints/vcu-small-debug.xdc From 00c30239bfaf5a78603d90151c37cbfbf7a8d7d0 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 22 Jul 2024 12:22:41 -0500 Subject: [PATCH 106/163] Cleaned up rvvisynth.sv --- src/rvvi/rvvisynth.sv | 126 ------------------------------------------ 1 file changed, 126 deletions(-) diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index 7700cc615..cbf7c30bf 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -69,132 +69,6 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [10+2*P.XLEN-1:0] Registers; logic [MAX_CSRS*(P.XLEN+12)-1:0] CSRs; - // get signals from the core. - if (`FPGA) begin -/* -----\/----- EXCLUDED -----\/----- - assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; - assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; - assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; - assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; - assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; - assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; - assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; - assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; - assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; - assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; - assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; - assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; - assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; - assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; - assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; - assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; - - assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 - assign CSRArray[16] = 0; // 12'hF11 - assign CSRArray[17] = 0; // 12'hF12 - assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 - assign CSRArray[19] = 0; // 12'hF15 - assign CSRArray[20] = 0; // 12'h34A - // supervisor CSRs - assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D - // user CSRs - assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 - -----/\----- EXCLUDED -----/\----- */ - end else begin // if (`FPGA) -/* -----\/----- EXCLUDED -----\/----- - assign StallE = dut.core.StallE; - assign StallM = dut.core.StallM; - assign StallW = dut.core.StallW; - assign FlushE = dut.core.FlushE; - assign FlushM = dut.core.FlushM; - assign FlushW = dut.core.FlushW; - assign InstrValidM = dut.core.ieu.InstrValidM; - assign InstrRawD = dut.core.ifu.InstrRawD; - assign PCM = dut.core.ifu.PCM; - assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = dut.core.TrapM; - assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = dut.core.ieu.dp.regf.a3; - assign GPRWen = dut.core.ieu.dp.regf.we3; - assign GPRValue = dut.core.ieu.dp.regf.wd3; - assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; - assign FPRWen = dut.core.fpu.fpu.fregfile.we4; - assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; - - assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 - assign CSRArray[16] = 0; // 12'hF11 - assign CSRArray[17] = 0; // 12'hF12 - assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 - assign CSRArray[19] = 0; // 12'hF15 - assign CSRArray[20] = 0; // 12'h34A - // supervisor CSRs - assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D - // user CSRs - assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 - -----/\----- EXCLUDED -----/\----- */ - end - - // assign XLENZeros = '0; // start out easy and just populate Required From a506d76149f83faeb96acb52efd10c4fe6265ea1 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Mon, 22 Jul 2024 12:36:39 -0500 Subject: [PATCH 107/163] Removed the old SDC. Added a second SPI peripheral that now will be used to control the SD card. SPI peripheral now outputs SPICLK. Removed references to the now non-existent external SDC in uncore. Removed all of the AXI Xilinx IP. --- fpga/src/fpgaTopArtyA7.sv | 828 ++++----------------------------- src/uncore/spi_apb.sv | 17 +- src/uncore/uncore.sv | 47 +- src/wally/wallypipelinedsoc.sv | 10 +- 4 files changed, 144 insertions(+), 758 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 9ddf958a7..6a2f055ba 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -29,38 +29,43 @@ import cvw::*; module fpgaTop - (input default_100mhz_clk, -(* mark_debug = "true" *) input resetn, - input south_reset, + (input default_100mhz_clk, + input resetn, + input south_reset, - input [3:0] GPI, - output [4:0] GPO, + // GPIO signals + input [3:0] GPI, + output [4:0] GPO, - input UARTSin, - output UARTSout, + // UART Signals + input UARTSin, + output UARTSout, - inout [3:0] SDCDat, - output SDCCLK, - inout SDCCmd, - input SDCCD, + // SDC Signals connecting to an SPI peripheral + input [3:0] SDCDat, + output SDCCLK, + output SDCCmd, + output SDCCD, - inout [15:0] ddr3_dq, - inout [1:0] ddr3_dqs_n, - inout [1:0] ddr3_dqs_p, - output [13:0] ddr3_addr, - output [2:0] ddr3_ba, - output ddr3_ras_n, - output ddr3_cas_n, - output ddr3_we_n, - output ddr3_reset_n, - output [0:0] ddr3_ck_p, - output [0:0] ddr3_ck_n, - output [0:0] ddr3_cke, - output [0:0] ddr3_cs_n, - output [1:0] ddr3_dm, - output [0:0] ddr3_odt + // Memory signals + inout [15:0] ddr3_dq, + inout [1:0] ddr3_dqs_n, + inout [1:0] ddr3_dqs_p, + output [13:0] ddr3_addr, + output [2:0] ddr3_ba, + output ddr3_ras_n, + output ddr3_cas_n, + output ddr3_we_n, + output ddr3_reset_n, + output [0:0] ddr3_ck_p, + output [0:0] ddr3_ck_n, + output [0:0] ddr3_cke, + output [0:0] ddr3_cs_n, + output [1:0] ddr3_dm, + output [0:0] ddr3_odt ); + // MMCM Signals wire CPUCLK; wire c0_ddr4_ui_clk_sync_rst; wire bus_struct_reset; @@ -69,6 +74,7 @@ module fpgaTop wire peripheral_aresetn; wire mb_reset; + // AHB Signals from Wally wire HCLKOpen; wire HRESETnOpen; wire [63:0] HRDATAEXT; @@ -87,12 +93,10 @@ module fpgaTop wire [3:0] HPROT; wire HMASTLOCK; + // GPIO Signals wire [31:0] GPIOIN, GPIOOUT, GPIOEN; - wire SDCCmdIn; - wire SDCCmdOE; - wire SDCCmdOut; - + // AHB to AXI Bridge Signals wire [3:0] m_axi_awid; wire [7:0] m_axi_awlen; wire [2:0] m_axi_awsize; @@ -100,40 +104,40 @@ module fpgaTop wire [3:0] m_axi_awcache; wire [31:0] m_axi_awaddr; wire [2:0] m_axi_awprot; - wire m_axi_awvalid; - wire m_axi_awready; - wire m_axi_awlock; + wire m_axi_awvalid; + wire m_axi_awready; + wire m_axi_awlock; wire [63:0] m_axi_wdata; wire [7:0] m_axi_wstrb; - wire m_axi_wlast; - wire m_axi_wvalid; - wire m_axi_wready; + wire m_axi_wlast; + wire m_axi_wvalid; + wire m_axi_wready; wire [3:0] m_axi_bid; wire [1:0] m_axi_bresp; - wire m_axi_bvalid; - wire m_axi_bready; + wire m_axi_bvalid; + wire m_axi_bready; wire [3:0] m_axi_arid; wire [7:0] m_axi_arlen; wire [2:0] m_axi_arsize; wire [1:0] m_axi_arburst; wire [2:0] m_axi_arprot; wire [3:0] m_axi_arcache; - wire m_axi_arvalid; + wire m_axi_arvalid; wire [31:0] m_axi_araddr; wire m_axi_arlock; - wire m_axi_arready; + wire m_axi_arready; wire [3:0] m_axi_rid; wire [63:0] m_axi_rdata; wire [1:0] m_axi_rresp; - wire m_axi_rvalid; - wire m_axi_rlast; - wire m_axi_rready; + wire m_axi_rvalid; + wire m_axi_rlast; + wire m_axi_rready; + // AXI Signals going out of Clock Converter wire [3:0] BUS_axi_arregion; wire [3:0] BUS_axi_arqos; wire [3:0] BUS_axi_awregion; wire [3:0] BUS_axi_awqos; - wire [3:0] BUS_axi_awid; wire [7:0] BUS_axi_awlen; wire [2:0] BUS_axi_awsize; @@ -173,250 +177,10 @@ module fpgaTop wire BUSCLK; wire sdio_reset_open; - // Crossbar to Bus ------------------------------------------------ - - wire s00_axi_aclk; - wire s00_axi_aresetn; - wire [3:0] s00_axi_awid; - wire [31:0]s00_axi_awaddr; - wire [7:0]s00_axi_awlen; - wire [2:0]s00_axi_awsize; - wire [1:0]s00_axi_awburst; - wire [0:0]s00_axi_awlock; - wire [3:0]s00_axi_awcache; - wire [2:0]s00_axi_awprot; - wire [3:0]s00_axi_awregion; - wire [3:0]s00_axi_awqos; - wire s00_axi_awvalid; - wire s00_axi_awready; - wire [63:0]s00_axi_wdata; - wire [7:0]s00_axi_wstrb; - wire s00_axi_wlast; - wire s00_axi_wvalid; - wire s00_axi_wready; - wire [1:0]s00_axi_bresp; - wire s00_axi_bvalid; - wire s00_axi_bready; - wire [3:0] s00_axi_arid; - wire [31:0]s00_axi_araddr; - wire [7:0]s00_axi_arlen; - wire [2:0]s00_axi_arsize; - wire [1:0]s00_axi_arburst; - wire [0:0]s00_axi_arlock; - wire [3:0]s00_axi_arcache; - wire [2:0]s00_axi_arprot; - wire [3:0]s00_axi_arregion; - wire [3:0]s00_axi_arqos; - wire s00_axi_arvalid; - wire s00_axi_arready; - wire [63:0]s00_axi_rdata; - wire [1:0]s00_axi_rresp; - wire s00_axi_rlast; - wire s00_axi_rvalid; - wire s00_axi_rready; - - wire [3:0] s00_axi_bid; - wire [3:0] s00_axi_rid; - - // 64to32 dwidth converter input interface------------------------- - wire s01_axi_aclk; - wire s01_axi_aresetn; - wire [3:0]s01_axi_awid; - wire [31:0]s01_axi_awaddr; - wire [7:0]s01_axi_awlen; - wire [2:0]s01_axi_awsize; - wire [1:0]s01_axi_awburst; - wire [0:0]s01_axi_awlock; - wire [3:0]s01_axi_awcache; - wire [2:0]s01_axi_awprot; - wire [3:0]s01_axi_awregion; - wire [3:0]s01_axi_awqos; // qos signals need to be 0 for SDC - wire s01_axi_awvalid; - wire s01_axi_awready; - wire [63:0]s01_axi_wdata; - wire [7:0]s01_axi_wstrb; - wire s01_axi_wlast; - wire s01_axi_wvalid; - wire s01_axi_wready; - wire [1:0]s01_axi_bresp; - wire s01_axi_bvalid; - wire s01_axi_bready; - wire [31:0]s01_axi_araddr; - wire [7:0]s01_axi_arlen; - wire [3:0] s01_axi_arid; - wire [2:0]s01_axi_arsize; - wire [1:0]s01_axi_arburst; - wire [0:0]s01_axi_arlock; - wire [3:0]s01_axi_arcache; - wire [2:0]s01_axi_arprot; - wire [3:0]s01_axi_arregion; - wire [3:0]s01_axi_arqos; // - wire s01_axi_arvalid; - wire s01_axi_arready; - wire [63:0]s01_axi_rdata; - wire [1:0]s01_axi_rresp; - wire s01_axi_rlast; - wire s01_axi_rvalid; - wire s01_axi_rready; - - // Output Interface - wire [31:0]axi4in_axi_awaddr; - wire [7:0]axi4in_axi_awlen; - wire [2:0]axi4in_axi_awsize; - wire [1:0]axi4in_axi_awburst; - wire [0:0]axi4in_axi_awlock; - wire [3:0]axi4in_axi_awcache; - wire [2:0]axi4in_axi_awprot; - wire [3:0]axi4in_axi_awregion; - wire [3:0]axi4in_axi_awqos; - wire axi4in_axi_awvalid; - wire axi4in_axi_awready; - wire [31:0]axi4in_axi_wdata; - wire [3:0]axi4in_axi_wstrb; - wire axi4in_axi_wlast; - wire axi4in_axi_wvalid; - wire axi4in_axi_wready; - wire [1:0]axi4in_axi_bresp; - wire axi4in_axi_bvalid; - wire axi4in_axi_bready; - wire [31:0]axi4in_axi_araddr; - wire [7:0]axi4in_axi_arlen; - wire [2:0]axi4in_axi_arsize; - wire [1:0]axi4in_axi_arburst; - wire [0:0]axi4in_axi_arlock; - wire [3:0]axi4in_axi_arcache; - wire [2:0]axi4in_axi_arprot; - wire [3:0]axi4in_axi_arregion; - wire [3:0]axi4in_axi_arqos; - wire axi4in_axi_arvalid; - wire axi4in_axi_arready; - wire [31:0]axi4in_axi_rdata; - wire [1:0]axi4in_axi_rresp; - wire axi4in_axi_rlast; - wire axi4in_axi_rvalid; - wire axi4in_axi_rready; - - // AXI4 to AXI4-Lite Protocol converter output - wire [31:0]SDCin_axi_awaddr; - wire [2:0]SDCin_axi_awprot; - wire SDCin_axi_awvalid; - wire SDCin_axi_awready; - wire [31:0]SDCin_axi_wdata; - wire [3:0]SDCin_axi_wstrb; - wire SDCin_axi_wvalid; - wire SDCin_axi_wready; - wire [1:0]SDCin_axi_bresp; - wire SDCin_axi_bvalid; - wire SDCin_axi_bready; - wire [31:0]SDCin_axi_araddr; - wire [2:0]SDCin_axi_arprot; - wire SDCin_axi_arvalid; - wire SDCin_axi_arready; - wire [31:0]SDCin_axi_rdata; - wire [1:0]SDCin_axi_rresp; - wire SDCin_axi_rvalid; - wire SDCin_axi_rready; - // ---------------------------------------------------------------- - - // 32to64 dwidth converter input interface ----------------------- - wire [31:0]SDCout_axi_awaddr; - wire [7:0]SDCout_axi_awlen; - wire [2:0]SDCout_axi_awsize; - wire [1:0]SDCout_axi_awburst; - wire [0:0]SDCout_axi_awlock; - wire [3:0]SDCout_axi_awcache; - wire [2:0]SDCout_axi_awprot; - wire [3:0]SDCout_axi_awregion; - wire [3:0]SDCout_axi_awqos; - wire SDCout_axi_awvalid; - wire SDCout_axi_awready; - wire [31:0]SDCout_axi_wdata; - wire [3:0]SDCout_axi_wstrb; - wire SDCout_axi_wlast; - wire SDCout_axi_wvalid; - wire SDCout_axi_wready; - wire [1:0]SDCout_axi_bresp; - wire SDCout_axi_bvalid; - wire SDCout_axi_bready; - wire [31:0]SDCout_axi_araddr; - wire [7:0]SDCout_axi_arlen; - wire [2:0]SDCout_axi_arsize; - wire [1:0]SDCout_axi_arburst; - wire [0:0]SDCout_axi_arlock; - wire [3:0]SDCout_axi_arcache; - wire [2:0]SDCout_axi_arprot; - wire [3:0]SDCout_axi_arregion; - wire [3:0]SDCout_axi_arqos; - wire SDCout_axi_arvalid; - wire SDCout_axi_arready; - wire [31:0]SDCout_axi_rdata; - wire [1:0]SDCout_axi_rresp; - wire SDCout_axi_rlast; - wire SDCout_axi_rvalid; - wire SDCout_axi_rready; - - // Output Interface - wire [3:0]m01_axi_awid; - wire [31:0]m01_axi_awaddr; - wire [7:0]m01_axi_awlen; - wire [2:0]m01_axi_awsize; - wire [1:0]m01_axi_awburst; - wire [0:0]m01_axi_awlock; - wire [3:0]m01_axi_awcache; - wire [2:0]m01_axi_awprot; - wire [3:0]m01_axi_awregion; - wire [3:0]m01_axi_awqos; - wire m01_axi_awvalid; - wire m01_axi_awready; - wire [63:0]m01_axi_wdata; - wire [7:0]m01_axi_wstrb; - wire m01_axi_wlast; - wire m01_axi_wvalid; - wire m01_axi_wready; - wire [3:0] m01_axi_bid; - wire [1:0]m01_axi_bresp; - wire m01_axi_bvalid; - wire m01_axi_bready; - wire [3:0] m01_axi_arid; - wire [31:0]m01_axi_araddr; - wire [7:0]m01_axi_arlen; - wire [2:0]m01_axi_arsize; - wire [1:0]m01_axi_arburst; - wire [0:0]m01_axi_arlock; - wire [3:0]m01_axi_arcache; - wire [2:0]m01_axi_arprot; - wire [3:0]m01_axi_arregion; - wire [3:0]m01_axi_arqos; - wire m01_axi_arvalid; - wire m01_axi_arready; - wire [3:0] m01_axi_rid; - wire [63:0]m01_axi_rdata; - wire [1:0]m01_axi_rresp; - wire m01_axi_rlast; - wire m01_axi_rvalid; - wire m01_axi_rready; - - // Old SDC input - // wire [3:0] SDCDatIn; - - // New SDC Command IOBUF connections - wire sd_cmd_i; - wire sd_cmd_reg_o; - wire sd_cmd_reg_t; - - // SD Card Interrupt signal - wire SDCIntr; - - // New SDC Data IOBUF connections - wire [3:0] sd_dat_i; - wire [3:0] sd_dat_reg_o; - wire sd_dat_reg_t; - - - wire c0_init_calib_complete; + wire c0_init_calib_complete; wire dbg_clk; wire [511 : 0] dbg_bus; - wire ui_clk_sync_rst; + wire ui_clk_sync_rst; wire CLK208; wire clk167; @@ -425,9 +189,9 @@ module fpgaTop wire app_sr_active; wire app_ref_ack; wire app_zq_ack; - wire mmcm_locked; + wire mmcm_locked; wire [11:0] device_temp; - wire mmcm1_locked; + wire mmcm1_locked; assign GPIOIN = {28'b0, GPI}; @@ -436,6 +200,11 @@ module fpgaTop assign cpu_reset = bus_struct_reset; assign calib = c0_init_calib_complete; + logic [3:0] SDCCS; + assign SDCCD = SDCCS[0]; + logic SDCIn; + assign SDCIn = SDCDat[0]; + // mmcm // the ddr3 mig7 requires 2 input clocks @@ -449,26 +218,7 @@ module fpgaTop .reset(1'b0), .locked(mmcm1_locked), .clk_in1(default_100mhz_clk)); - -/* -----\/----- EXCLUDED -----\/----- - // SD Card Tristate - IOBUF iobufSDCMD(.T(~SDCCmdOE), // iobuf's T is active low - .I(SDCCmdOut), - .O(SDCCmdIn), - .IO(SDCCmd)); - -----/\----- EXCLUDED -----/\----- */ - // IOBUFS for new SDC peripheral - IOBUF IOBUF_cmd (.O(sd_cmd_i), .IO(SDCCmd), .I(sd_cmd_reg_o), .T(sd_cmd_reg_t)); - genvar i; - generate - for (i = 0; i < 4; i = i + 1) begin - IOBUF iobufSDCDat(.T(sd_dat_reg_t), - .I(sd_dat_reg_o[i]), - .O(sd_dat_i[i]), - .IO(SDCDat[i]) ); - end - endgenerate // reset controller XILINX IP @@ -484,11 +234,9 @@ module fpgaTop .interconnect_aresetn(interconnect_aresetn), //open .peripheral_aresetn(peripheral_aresetn)); - // wally - // RT and JP: FIXME add sdc interrupt and HSELEXTSDC, remove old sdc after the new sdc ahb version is implemented - `include "parameter-defs.vh" - + + // Wally wallypipelinedsoc #(P) wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, @@ -496,7 +244,7 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr); + .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); // ahb lite to axi bridge @@ -551,432 +299,49 @@ module fpgaTop .m_axi_rlast(m_axi_rlast), .m_axi_rready(m_axi_rready)); - // AXI Crossbar for arbitrating the SDC and CPU -------------- - xlnx_axi_crossbar xlnx_axi_crossbar_0 - (.aclk(CPUCLK), - .aresetn(peripheral_aresetn), - - // Connect Masters - .s_axi_awid({4'b1000, m_axi_awid}), - .s_axi_awaddr({m01_axi_awaddr, m_axi_awaddr}), - .s_axi_awlen({m01_axi_awlen, m_axi_awlen}), - .s_axi_awsize({m01_axi_awsize, m_axi_awsize}), - .s_axi_awburst({m01_axi_awburst, m_axi_awburst}), - .s_axi_awlock({m01_axi_awlock, m_axi_awlock}), - .s_axi_awcache({m01_axi_awcache, m_axi_awcache}), - .s_axi_awprot({m01_axi_awprot, m_axi_awprot}), - .s_axi_awqos(8'b0), - .s_axi_awvalid({m01_axi_awvalid, m_axi_awvalid}), - .s_axi_awready({m01_axi_awready, m_axi_awready}), - .s_axi_wdata({m01_axi_wdata, m_axi_wdata}), - .s_axi_wstrb({m01_axi_wstrb, m_axi_wstrb}), - .s_axi_wlast({m01_axi_wlast, m_axi_wlast}), - .s_axi_wvalid({m01_axi_wvalid, m_axi_wvalid}), - .s_axi_wready({m01_axi_wready, m_axi_wready}), - .s_axi_bid({m01_axi_bid, m_axi_bid}), - .s_axi_bresp({m01_axi_bresp, m_axi_bresp}), - .s_axi_bvalid({m01_axi_bvalid, m_axi_bvalid}), - .s_axi_bready({m01_axi_bready, m_axi_bready}), - .s_axi_arid({4'b1000, m_axi_arid}), - .s_axi_araddr({m01_axi_araddr, m_axi_araddr}), - .s_axi_arlen({m01_axi_arlen, m_axi_arlen}), - .s_axi_arsize({m01_axi_arsize, m_axi_arsize}), - .s_axi_arburst({m01_axi_arburst, m_axi_arburst}), - .s_axi_arlock({m01_axi_arlock, m_axi_arlock}), - .s_axi_arcache({m01_axi_arcache, m_axi_arcache}), - .s_axi_arprot({m01_axi_arprot, m_axi_arprot}), - .s_axi_arqos(8'b0), - .s_axi_arvalid({m01_axi_arvalid, m_axi_arvalid}), - .s_axi_arready({m01_axi_arready, m_axi_arready}), - .s_axi_rid({m01_axi_rid, m_axi_rid}), - .s_axi_rdata({m01_axi_rdata, m_axi_rdata}), - .s_axi_rresp({m01_axi_rresp, m_axi_rresp}), - .s_axi_rlast({m01_axi_rlast, m_axi_rlast}), - .s_axi_rvalid({m01_axi_rvalid, m_axi_rvalid}), - .s_axi_rready({m01_axi_rready, m_axi_rready}), - - // Connect Slaves - .m_axi_awid({s01_axi_awid, s00_axi_awid}), - .m_axi_awlen({s01_axi_awlen, s00_axi_awlen}), - .m_axi_awsize({s01_axi_awsize, s00_axi_awsize}), - .m_axi_awburst({s01_axi_awburst, s00_axi_awburst}), - .m_axi_awcache({s01_axi_awcache, s00_axi_awcache}), - .m_axi_awaddr({s01_axi_awaddr, s00_axi_awaddr}), - .m_axi_awprot({s01_axi_awprot, s00_axi_awprot}), - .m_axi_awregion({s01_axi_awregion, s00_axi_awregion}), - .m_axi_awqos({s01_axi_awqos, s00_axi_awqos}), - .m_axi_awvalid({s01_axi_awvalid, s00_axi_awvalid}), - .m_axi_awready({s01_axi_awready, s00_axi_awready}), - .m_axi_awlock({s01_axi_awlock, s00_axi_awlock}), - .m_axi_wdata({s01_axi_wdata, s00_axi_wdata}), - .m_axi_wstrb({s01_axi_wstrb, s00_axi_wstrb}), - .m_axi_wlast({s01_axi_wlast, s00_axi_wlast}), - .m_axi_wvalid({s01_axi_wvalid, s00_axi_wvalid}), - .m_axi_wready({s01_axi_wready, s00_axi_wready}), - .m_axi_bid({4'b1000, s00_axi_bid}), - .m_axi_bresp({s01_axi_bresp, s00_axi_bresp}), - .m_axi_bvalid({s01_axi_bvalid, s00_axi_bvalid}), - .m_axi_bready({s01_axi_bready, s00_axi_bready}), - .m_axi_arid({s01_axi_arid, s00_axi_arid}), - .m_axi_arlen({s01_axi_arlen, s00_axi_arlen}), - .m_axi_arsize({s01_axi_arsize, s00_axi_arsize}), - .m_axi_arburst({s01_axi_arburst, s00_axi_arburst}), - .m_axi_arprot({s01_axi_arprot, s00_axi_arprot}), - .m_axi_arregion({s01_axi_arregion, s00_axi_arregion}), - .m_axi_arqos({s01_axi_arqos, s00_axi_arqos}), - .m_axi_arcache({s01_axi_arcache, s00_axi_arcache}), - .m_axi_arvalid({s01_axi_arvalid, s00_axi_arvalid}), - .m_axi_araddr({s01_axi_araddr, s00_axi_araddr}), - .m_axi_arlock({s01_axi_arlock, s00_axi_arlock}), - .m_axi_arready({s01_axi_arready, s00_axi_arready}), - .m_axi_rid({4'b1000, s00_axi_rid}), - .m_axi_rdata({s01_axi_rdata, s00_axi_rdata}), - .m_axi_rresp({s01_axi_rresp, s00_axi_rresp}), - .m_axi_rvalid({s01_axi_rvalid, s00_axi_rvalid}), - .m_axi_rlast({s01_axi_rlast, s00_axi_rlast}), - .m_axi_rready({s01_axi_rready, s00_axi_rready}) - ); - - // ----------------------------------------------------- - - // SDC Implementation ---------------------------------- - // - // The SDC peripheral from Eugene Tarassov takes in an AXI4Lite - // interface and outputs an AXI4 interface. In order to convert from - // one to the other, we use these dwidth converters to make sure the - // bit widths match the rest of the bus. - - xlnx_axi_dwidth_conv_64to32 axi_conv_down - (.s_axi_aclk(CPUCLK), - .s_axi_aresetn(peripheral_aresetn), - - // Slave interface - .s_axi_awaddr(s01_axi_awaddr), - .s_axi_awlen(s01_axi_awlen), - .s_axi_awsize(s01_axi_awsize), - .s_axi_awburst(s01_axi_awburst), - .s_axi_awlock(s01_axi_awlock), - .s_axi_awcache(s01_axi_awcache), - .s_axi_awprot(s01_axi_awprot), - .s_axi_awregion(s01_axi_awregion), - .s_axi_awqos(4'b0), - .s_axi_awvalid(s01_axi_awvalid), - .s_axi_awready(s01_axi_awready), - .s_axi_wdata(s01_axi_wdata), - .s_axi_wstrb(s01_axi_wstrb), - .s_axi_wlast(s01_axi_wlast), - .s_axi_wvalid(s01_axi_wvalid), - .s_axi_wready(s01_axi_wready), - .s_axi_bresp(s01_axi_bresp), - .s_axi_bvalid(s01_axi_bvalid), - .s_axi_bready(s01_axi_bready), - .s_axi_araddr(s01_axi_araddr), - .s_axi_arlen(s01_axi_arlen), - .s_axi_arsize(s01_axi_arsize), - .s_axi_arburst(s01_axi_arburst), - .s_axi_arlock(s01_axi_arlock), - .s_axi_arcache(s01_axi_arcache), - .s_axi_arprot(s01_axi_arprot), - .s_axi_arregion(s01_axi_arregion), - .s_axi_arqos(4'b0), - .s_axi_arvalid(s01_axi_arvalid), - .s_axi_arready(s01_axi_arready), - .s_axi_rdata(s01_axi_rdata), - .s_axi_rresp(s01_axi_rresp), - .s_axi_rlast(s01_axi_rlast), - .s_axi_rvalid(s01_axi_rvalid), - .s_axi_rready(s01_axi_rready), - - // Master interface - .m_axi_awaddr(axi4in_axi_awaddr), - .m_axi_awlen(axi4in_axi_awlen), - .m_axi_awsize(axi4in_axi_awsize), - .m_axi_awburst(axi4in_axi_awburst), - .m_axi_awlock(axi4in_axi_awlock), - .m_axi_awcache(axi4in_axi_awcache), - .m_axi_awprot(axi4in_axi_awprot), - .m_axi_awregion(axi4in_axi_awregion), - .m_axi_awqos(axi4in_axi_awqos), - .m_axi_awvalid(axi4in_axi_awvalid), - .m_axi_awready(axi4in_axi_awready), - .m_axi_wdata(axi4in_axi_wdata), - .m_axi_wstrb(axi4in_axi_wstrb), - .m_axi_wlast(axi4in_axi_wlast), - .m_axi_wvalid(axi4in_axi_wvalid), - .m_axi_wready(axi4in_axi_wready), - .m_axi_bresp(axi4in_axi_bresp), - .m_axi_bvalid(axi4in_axi_bvalid), - .m_axi_bready(axi4in_axi_bready), - .m_axi_araddr(axi4in_axi_araddr), - .m_axi_arlen(axi4in_axi_arlen), - .m_axi_arsize(axi4in_axi_arsize), - .m_axi_arburst(axi4in_axi_arburst), - .m_axi_arlock(axi4in_axi_arlock), - .m_axi_arcache(axi4in_axi_arcache), - .m_axi_arprot(axi4in_axi_arprot), - .m_axi_arregion(axi4in_axi_arregion), - .m_axi_arqos(axi4in_axi_arqos), - .m_axi_arvalid(axi4in_axi_arvalid), - .m_axi_arready(axi4in_axi_arready), - .m_axi_rdata(axi4in_axi_rdata), - .m_axi_rresp(axi4in_axi_rresp), - .m_axi_rlast(axi4in_axi_rlast), - .m_axi_rvalid(axi4in_axi_rvalid), - .m_axi_rready(axi4in_axi_rready) - ); - - xlnx_axi_prtcl_conv axi4tolite - (.aclk(CPUCLK), - .aresetn(peripheral_aresetn), - - // AXI4 In - .s_axi_awaddr(axi4in_axi_awaddr), - .s_axi_awlen(axi4in_axi_awlen), - .s_axi_awsize(axi4in_axi_awsize), - .s_axi_awburst(axi4in_axi_awburst), - .s_axi_awlock(axi4in_axi_awlock), - .s_axi_awcache(axi4in_axi_awcache), - .s_axi_awprot(axi4in_axi_awprot), - .s_axi_awregion(axi4in_axi_awregion), - .s_axi_awqos(axi4in_axi_awqos), - .s_axi_awvalid(axi4in_axi_awvalid), - .s_axi_awready(axi4in_axi_awready), - .s_axi_wdata(axi4in_axi_wdata), - .s_axi_wstrb(axi4in_axi_wstrb), - .s_axi_wlast(axi4in_axi_wlast), - .s_axi_wvalid(axi4in_axi_wvalid), - .s_axi_wready(axi4in_axi_wready), - .s_axi_bresp(axi4in_axi_bresp), - .s_axi_bvalid(axi4in_axi_bvalid), - .s_axi_bready(axi4in_axi_bready), - .s_axi_araddr(axi4in_axi_araddr), - .s_axi_arlen(axi4in_axi_arlen), - .s_axi_arsize(axi4in_axi_arsize), - .s_axi_arburst(axi4in_axi_arburst), - .s_axi_arlock(axi4in_axi_arlock), - .s_axi_arcache(axi4in_axi_arcache), - .s_axi_arprot(axi4in_axi_arprot), - .s_axi_arregion(axi4in_axi_arregion), - .s_axi_arqos(axi4in_axi_arqos), - .s_axi_arvalid(axi4in_axi_arvalid), - .s_axi_arready(axi4in_axi_arready), - .s_axi_rdata(axi4in_axi_rdata), - .s_axi_rresp(axi4in_axi_rresp), - .s_axi_rlast(axi4in_axi_rlast), - .s_axi_rvalid(axi4in_axi_rvalid), - .s_axi_rready(axi4in_axi_rready), - - // AXI4Lite Out - .m_axi_awaddr(SDCin_axi_awaddr), - .m_axi_awprot(SDCin_axi_awprot), - .m_axi_awvalid(SDCin_axi_awvalid), - .m_axi_awready(SDCin_axi_awready), - .m_axi_wdata(SDCin_axi_wdata), - .m_axi_wstrb(SDCin_axi_wstrb), - .m_axi_wvalid(SDCin_axi_wvalid), - .m_axi_wready(SDCin_axi_wready), - .m_axi_bresp(SDCin_axi_bresp), - .m_axi_bvalid(SDCin_axi_bvalid), - .m_axi_bready(SDCin_axi_bready), - .m_axi_araddr(SDCin_axi_araddr), - .m_axi_arprot(SDCin_axi_arprot), - .m_axi_arvalid(SDCin_axi_arvalid), - .m_axi_arready(SDCin_axi_arready), - .m_axi_rdata(SDCin_axi_rdata), - .m_axi_rresp(SDCin_axi_rresp), - .m_axi_rvalid(SDCin_axi_rvalid), - .m_axi_rready(SDCin_axi_rready) - - ); - - - sdc_controller axiSDC - (.clock(CPUCLK), - .async_resetn(peripheral_aresetn), - - // Slave Interface - .s_axi_awaddr({8'b0, SDCin_axi_awaddr[7:0]}), - .s_axi_awvalid(SDCin_axi_awvalid), - .s_axi_awready(SDCin_axi_awready), - .s_axi_wdata(SDCin_axi_wdata), - .s_axi_wvalid(SDCin_axi_wvalid), - .s_axi_wready(SDCin_axi_wready), - .s_axi_bresp(SDCin_axi_bresp), - .s_axi_bvalid(SDCin_axi_bvalid), - .s_axi_bready(SDCin_axi_bready), - .s_axi_araddr({8'b0, SDCin_axi_araddr[7:0]}), - .s_axi_arvalid(SDCin_axi_arvalid), - .s_axi_arready(SDCin_axi_arready), - .s_axi_rdata(SDCin_axi_rdata), - .s_axi_rresp(SDCin_axi_rresp), - .s_axi_rvalid(SDCin_axi_rvalid), - .s_axi_rready(SDCin_axi_rready), - .sdio_reset(sdio_reset_open), - - // Master Interface - .m_axi_awaddr(SDCout_axi_awaddr), - .m_axi_awlen(SDCout_axi_awlen), - .m_axi_awvalid(SDCout_axi_awvalid), - .m_axi_awready(SDCout_axi_awready), - .m_axi_wdata(SDCout_axi_wdata), - .m_axi_wlast(SDCout_axi_wlast), - .m_axi_wvalid(SDCout_axi_wvalid), - .m_axi_wready(SDCout_axi_wready), - .m_axi_bresp(SDCout_axi_bresp), - .m_axi_bvalid(SDCout_axi_bvalid), - .m_axi_bready(SDCout_axi_bready), - .m_axi_araddr(SDCout_axi_araddr), - .m_axi_arlen(SDCout_axi_arlen), - .m_axi_arvalid(SDCout_axi_arvalid), - .m_axi_arready(SDCout_axi_arready), - .m_axi_rdata(SDCout_axi_rdata), - .m_axi_rlast(SDCout_axi_rlast), - .m_axi_rresp(SDCout_axi_rresp), - .m_axi_rvalid(SDCout_axi_rvalid), - .m_axi_rready(SDCout_axi_rready), - - // SDC interface - //.sdio_cmd(1'b0), - //.sdio_dat(4'b0), - //.sdio_cd(1'b0) - - .sd_dat_reg_t(sd_dat_reg_t), - .sd_dat_reg_o(sd_dat_reg_o), - .sd_dat_i(sd_dat_i), - - .sd_cmd_reg_t(sd_cmd_reg_t), - .sd_cmd_reg_o(sd_cmd_reg_o), - .sd_cmd_i(sd_cmd_i), - - .sdio_clk(SDCCLK), - .sdio_cd(SDCCD), - - .interrupt(SDCIntr) - ); - - xlnx_axi_dwidth_conv_32to64 axi_conv_up - (.s_axi_aclk(CPUCLK), - .s_axi_aresetn(peripheral_aresetn), - - // Slave interface - .s_axi_awaddr(SDCout_axi_awaddr), - .s_axi_awlen(SDCout_axi_awlen), - .s_axi_awsize(3'b010), - .s_axi_awburst(2'b01), - .s_axi_awlock(1'b0), - .s_axi_awcache(4'b0), - .s_axi_awprot(3'b0), - .s_axi_awregion(4'b0), - .s_axi_awqos(4'b0), - .s_axi_awvalid(SDCout_axi_awvalid), - .s_axi_awready(SDCout_axi_awready), - .s_axi_wdata(SDCout_axi_wdata), - .s_axi_wstrb(8'b11111111), - .s_axi_wlast(SDCout_axi_wlast), - .s_axi_wvalid(SDCout_axi_wvalid), - .s_axi_wready(SDCout_axi_wready), - .s_axi_bresp(SDCout_axi_bresp), - .s_axi_bvalid(SDCout_axi_bvalid), - .s_axi_bready(SDCout_axi_bready), - .s_axi_araddr(SDCout_axi_araddr), - .s_axi_arlen(SDCout_axi_arlen), - .s_axi_arsize(3'b010), - .s_axi_arburst(2'b01), - .s_axi_arlock(1'b0), - .s_axi_arcache(4'b0), - .s_axi_arprot(3'b0), - .s_axi_arregion(4'b0), - .s_axi_arqos(4'b0), - .s_axi_arvalid(SDCout_axi_arvalid), - .s_axi_arready(SDCout_axi_arready), - .s_axi_rdata(SDCout_axi_rdata), - .s_axi_rresp(SDCout_axi_rresp), - .s_axi_rlast(SDCout_axi_rlast), - .s_axi_rvalid(SDCout_axi_rvalid), - .s_axi_rready(SDCout_axi_rready), - - // Master interface - .m_axi_awaddr(m01_axi_awaddr), - .m_axi_awlen(m01_axi_awlen), - .m_axi_awsize(m01_axi_awsize), - .m_axi_awburst(m01_axi_awburst), - .m_axi_awlock(m01_axi_awlock), - .m_axi_awcache(m01_axi_awcache), - .m_axi_awprot(m01_axi_awprot), - .m_axi_awregion(m01_axi_awregion), - .m_axi_awqos(m01_axi_awqos), - .m_axi_awvalid(m01_axi_awvalid), - .m_axi_awready(m01_axi_awready), - .m_axi_wdata(m01_axi_wdata), - .m_axi_wstrb(m01_axi_wstrb), - .m_axi_wlast(m01_axi_wlast), - .m_axi_wvalid(m01_axi_wvalid), - .m_axi_wready(m01_axi_wready), - .m_axi_bresp(m01_axi_bresp), - .m_axi_bvalid(m01_axi_bvalid), - .m_axi_bready(m01_axi_bready), - .m_axi_araddr(m01_axi_araddr), - .m_axi_arlen(m01_axi_arlen), - .m_axi_arsize(m01_axi_arsize), - .m_axi_arburst(m01_axi_arburst), - .m_axi_arlock(m01_axi_arlock), - .m_axi_arcache(m01_axi_arcache), - .m_axi_arprot(m01_axi_arprot), - .m_axi_arregion(m01_axi_arregion), - .m_axi_arqos(m01_axi_arqos), - .m_axi_arvalid(m01_axi_arvalid), - .m_axi_arready(m01_axi_arready), - .m_axi_rdata(m01_axi_rdata), - .m_axi_rresp(m01_axi_rresp), - .m_axi_rlast(m01_axi_rlast), - .m_axi_rvalid(m01_axi_rvalid), - .m_axi_rready(m01_axi_rready) - ); - - // End SDC signals -------------------------------------------- - + // AXI Clock Converter xlnx_axi_clock_converter xlnx_axi_clock_converter_0 (.s_axi_aclk(CPUCLK), .s_axi_aresetn(peripheral_aresetn), - .s_axi_awid(s00_axi_awid), - .s_axi_awlen(s00_axi_awlen), - .s_axi_awsize(s00_axi_awsize), - .s_axi_awburst(s00_axi_awburst), - .s_axi_awcache(s00_axi_awcache), - .s_axi_awaddr(s00_axi_awaddr[30:0] ), - .s_axi_awprot(s00_axi_awprot), + .s_axi_awid(m_axi_awid), + .s_axi_awlen(m_axi_awlen), + .s_axi_awsize(m_axi_awsize), + .s_axi_awburst(m_axi_awburst), + .s_axi_awcache(m_axi_awcache), + .s_axi_awaddr(m_axi_awaddr[30:0] ), + .s_axi_awprot(m_axi_awprot), .s_axi_awregion(4'b0), // this could be a bug. bridge does not have these outputs .s_axi_awqos(4'b0), // this could be a bug. bridge does not have these outputs - .s_axi_awvalid(s00_axi_awvalid), - .s_axi_awready(s00_axi_awready), - .s_axi_awlock(s00_axi_awlock), - .s_axi_wdata(s00_axi_wdata), - .s_axi_wstrb(s00_axi_wstrb), - .s_axi_wlast(s00_axi_wlast), - .s_axi_wvalid(s00_axi_wvalid), - .s_axi_wready(s00_axi_wready), - .s_axi_bid(s00_axi_bid), - .s_axi_bresp(s00_axi_bresp), - .s_axi_bvalid(s00_axi_bvalid), - .s_axi_bready(s00_axi_bready), - .s_axi_arid(s00_axi_arid), - .s_axi_arlen(s00_axi_arlen), - .s_axi_arsize(s00_axi_arsize), - .s_axi_arburst(s00_axi_arburst), - .s_axi_arprot(s00_axi_arprot), + .s_axi_awvalid(m_axi_awvalid), + .s_axi_awready(m_axi_awready), + .s_axi_awlock(m_axi_awlock), + .s_axi_wdata(m_axi_wdata), + .s_axi_wstrb(m_axi_wstrb), + .s_axi_wlast(m_axi_wlast), + .s_axi_wvalid(m_axi_wvalid), + .s_axi_wready(m_axi_wready), + .s_axi_bid(m_axi_bid), + .s_axi_bresp(m_axi_bresp), + .s_axi_bvalid(m_axi_bvalid), + .s_axi_bready(m_axi_bready), + .s_axi_arid(m_axi_arid), + .s_axi_arlen(m_axi_arlen), + .s_axi_arsize(m_axi_arsize), + .s_axi_arburst(m_axi_arburst), + .s_axi_arprot(m_axi_arprot), .s_axi_arregion(4'b0), // this could be a bug. bridge does not have these outputs .s_axi_arqos(4'b0), // this could be a bug. bridge does not have these outputs - .s_axi_arcache(s00_axi_arcache), - .s_axi_arvalid(s00_axi_arvalid), - .s_axi_araddr(s00_axi_araddr[30:0]), - .s_axi_arlock(s00_axi_arlock), - .s_axi_arready(s00_axi_arready), - .s_axi_rid(s00_axi_rid), - .s_axi_rdata(s00_axi_rdata), - .s_axi_rresp(s00_axi_rresp), - .s_axi_rvalid(s00_axi_rvalid), - .s_axi_rlast(s00_axi_rlast), - .s_axi_rready(s00_axi_rready), + .s_axi_arcache(m_axi_arcache), + .s_axi_arvalid(m_axi_arvalid), + .s_axi_araddr(m_axi_araddr[30:0]), + .s_axi_arlock(m_axi_arlock), + .s_axi_arready(m_axi_arready), + .s_axi_rid(m_axi_rid), + .s_axi_rdata(m_axi_rdata), + .s_axi_rresp(m_axi_rresp), + .s_axi_rvalid(m_axi_rvalid), + .s_axi_rlast(m_axi_rlast), + .s_axi_rready(m_axi_rready), .m_axi_aclk(BUSCLK), .m_axi_aresetn(resetn), @@ -1020,6 +385,7 @@ module fpgaTop .m_axi_rlast(BUS_axi_rlast), .m_axi_rready(BUS_axi_rready)); + // DDR3 Controller xlnx_ddr3 xlnx_ddr3_c0 ( // ddr3 I/O diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 94f188120..e9c04bca8 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -42,7 +42,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( output logic SPIOut, input logic SPIIn, output logic [3:0] SPICS, - output logic SPIIntr + output logic SPIIntr, + output logic SPICLK ); // register map @@ -99,7 +100,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( rsrstatetype ReceiveState; // Transmission signals - logic sck; + // logic sck; logic [11:0] DivCounter; // Counter for sck logic SCLKenable; // Flip flop enable high every sclk edge @@ -358,7 +359,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull); assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef; - assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1]; + assign SPICLK = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1]; assign Active = (state == ACTIVE_0 | state == ACTIVE_1); assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0); assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4]))); @@ -368,11 +369,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Signal tracks which edge of sck to shift data always_comb case(SckMode[1:0]) - 2'b00: ShiftEdge = ~sck & SCLKenable; - 2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable); - 2'b10: ShiftEdge = sck & SCLKenable; - 2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable); - default: ShiftEdge = sck & SCLKenable; + 2'b00: ShiftEdge = ~SPICLK & SCLKenable; + 2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); + 2'b10: ShiftEdge = SPICLK & SCLKenable; + 2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); + default: ShiftEdge = SPICLK & SCLKenable; endcase // Transmit shift register diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 39a2be09a..dad558c19 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -46,7 +46,6 @@ module uncore import cvw::*; #(parameter cvw_t P)( output logic [P.AHBW-1:0] HRDATA, output logic HREADY, HRESP, output logic HSELEXT, - output logic HSELEXTSDC, // peripheral pins output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT output logic MExtInt, SExtInt, // External interrupts from PLIC @@ -55,16 +54,20 @@ module uncore import cvw::*; #(parameter cvw_t P)( output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable input logic UARTSin, // UART serial input output logic UARTSout, // UART serial output - input logic SDCIntr, input logic SPIIn, output logic SPIOut, - output logic [3:0] SPICS + output logic [3:0] SPICS, + output logic SPICLK, + input logic SDCIn, + output logic SDCCmd, + output logic [3:0] SDCCS, + output logic SDCCLK ); logic [P.XLEN-1:0] HREADRam, HREADSDC; logic [11:0] HSELRegions; - logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSPI; + logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART,HSELSDC, HSELSPI; logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID; logic HRESPRam, HRESPSDC; logic HREADYRam, HRESPSDCD; @@ -85,8 +88,8 @@ module uncore import cvw::*; #(parameter cvw_t P)( /* verilator lint_on UNDRIVEN */ logic [P.XLEN-1:0] HREADBRIDGE; logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED; - - (* mark_debug = "true" *) logic HSELEXTSDCD; + /* SDC Interrupt (SPI Controller) */ + logic SDCIntr; // Determine which region of physical memory (if any) is being accessed @@ -95,14 +98,14 @@ module uncore import cvw::*; #(parameter cvw_t P)( adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1]; + assign {HSELSPI, HSELSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1]; // AHB -> APB bridge - ahbapbbridge #(P, 5) ahbapbbridge ( - .HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, + ahbapbbridge #(P, 6) ahbapbbridge ( + .HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO, HSELSDC}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE), .PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA); - assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI; // if any of the bridge signals are selected + assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI | HSELSDC; // if any of the bridge signals are selected // on-chip RAM if (P.UNCORE_RAM_SUPPORTED) begin : ram @@ -142,6 +145,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( end else begin : gpio assign GPIOOUT = '0; assign GPIOEN = '0; assign GPIOIntr = 1'b0; end + if (P.UART_SUPPORTED == 1) begin : uartgen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 uart_apb #(P) uart( .PCLK, .PRESETn, .PSEL(PSEL[3]), .PADDR(PADDR[2:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, @@ -152,28 +156,39 @@ module uncore import cvw::*; #(parameter cvw_t P)( end else begin : uart assign UARTSout = 1'b0; assign UARTIntr = 1'b0; end + if (P.SPI_SUPPORTED == 1) begin : spi spi_apb #(P) spi ( .PCLK, .PRESETn, .PSEL(PSEL[4]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, .PREADY(PREADY[4]), .PRDATA(PRDATA[4]), - .SPIOut, .SPIIn, .SPICS, .SPIIntr); + .SPIOut, .SPIIn, .SPICS, .SPICLK, .SPIIntr); end else begin : spi - assign SPIOut = 1'b0; assign SPICS = '0; assign SPIIntr = 1'b0; + assign SPIOut = 1'b0; assign SPICS = '0; assign SPIIntr = 1'b0; assign SPICLK = 1'b0; end + if (P.SDC_SUPPORTED == 1) begin : sdc + spi_apb #(P) sdc( + .PCLK, .PRESETN, .PSEL(.PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, + .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), + .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(.SDCIntr)); + end else begin : sdc + assign SDCCmd = '0; assign SDCCD = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; + end + + // AHB Read Multiplexer assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) | - ({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) | + ({P.XLEN{HSELEXTD}} & HRDATAEXT) | ({P.XLEN{HSELBRIDGED}} & HREADBRIDGE) | ({P.XLEN{HSELBootRomD}} & HREADBootRom); assign HRESP = HSELRamD & HRESPRam | - (HSELEXTD | HSELEXTSDCD) & HRESPEXT | + HSELEXTD & HRESPEXT | HSELBRIDGE & HRESPBRIDGE | HSELBootRomD & HRESPBootRom; assign HREADY = HSELRamD & HREADYRam | - (HSELEXTD | HSELEXTSDCD) & HREADYEXT | + HSELEXTD & HREADYEXT | HSELBRIDGED & HREADYBRIDGE | HSELBootRomD & HREADYBootRom | HSELNoneD; // don't lock up the bus if no region is being accessed @@ -184,7 +199,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( // device is ready. Hense this register must be selectively enabled by HREADY. // However on reset None must be seleted. flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1, - {HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD, + {HSELSPID, HSELSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD, HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD}); flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED); endmodule diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 9f5e5ee00..af9f0ff26 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -55,10 +55,14 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( output logic [31:0] GPIOEN, // output enables for GPIO input logic UARTSin, // UART serial data input output logic UARTSout, // UART serial data output - input logic SDCIntr, input logic SPIIn, // SPI pins in output logic SPIOut, // SPI pins out - output logic [3:0] SPICS // SPI chip select pins + output logic [3:0] SPICS, // SPI chip select pins + output logic SPICLK, // SPI clock + input logic SDCIn, // SDC DATA[0] to SPI DI + output logic SDCCmd, // SDC CMD from SPI DO + output logic [3:0] SDCCS, // SDC Card Detect from SPI CS + output logic SDCCLK // SDC Clock from SPI Clock ); // Uncore signals @@ -84,7 +88,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC, .MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, - .UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS); + .UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); end else begin assign {HRDATA, HREADY, HRESP, HSELEXT, HSELEXTSDC, MTimerInt, MSwInt, MExtInt, SExtInt, MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; From cec39fd3aa66a8ccc8fee528287134f3ccdfd643 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Mon, 22 Jul 2024 13:05:16 -0500 Subject: [PATCH 108/163] Added new SDC clock constraint. --- fpga/constraints/constraints-ArtyA7.xdc | 63 +++++++++++++------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 6fc660e8d..f466b0c30 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -4,6 +4,7 @@ # This clock is not used by wally or the AHB Bus. However it is used by the AXI BUS on the DD3 IP. #create_generated_clock -name CLKDiv64_Gen -source [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/I0] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/O] +create_generated_clock -name SPISDCClock -source [get_pins clk_out3_xlnx_mmcm] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncore.uncore/sdc.sdc/SPICLK] ##### clock ##### set_property PACKAGE_PIN E3 [get_ports {default_100mhz_clk}] @@ -74,41 +75,43 @@ set_property IOSTANDARD LVCMOS33 [get_ports {south_reset}] ##### SD Card I/O ##### #***** may have to switch to Pmod JB or JC. -set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}] -set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}] -set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}] -set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}] -set_property PACKAGE_PIN F3 [get_ports SDCCLK] -set_property PACKAGE_PIN D3 [get_ports {SDCCmd}] -set_property PACKAGE_PIN H2 [get_ports {SDCCD}] +#set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}] +#set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}] +#set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}] +#set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}] +#set_property PACKAGE_PIN F3 [get_ports SDCCLK] +#set_property PACKAGE_PIN D3 [get_ports {SDCCmd}] +#set_property PACKAGE_PIN H2 [get_ports {SDCCD}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCCD}] +#set_property PULLUP true [get_ports {SDCDat[3]}] +#set_property PULLUP true [get_ports {SDCDat[2]}] +#set_property PULLUP true [get_ports {SDCDat[1]}] +#set_property PULLUP true [get_ports {SDCDat[0]}] +#set_property PULLUP true [get_ports {SDCCmd}] +#set_property PULLUP true [get_ports {SDCCD}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}] -set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCCD}] -set_property PULLUP true [get_ports {SDCDat[3]}] -set_property PULLUP true [get_ports {SDCDat[2]}] -set_property PULLUP true [get_ports {SDCDat[1]}] -set_property PULLUP true [get_ports {SDCDat[0]}] -set_property PULLUP true [get_ports {SDCCmd}] -set_property PULLUP true [get_ports {SDCCD}] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[3]}] +set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] +set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] +set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[0]}] +set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCClk}] +set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] +set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] +set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCDat[*]}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCDat[*]}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.500 [get_ports {SDCDat[*]}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 21.000 [get_ports {SDCDat[*]}] +set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}] +set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.500 [get_ports {SDCCmd}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 14.000 [get_ports {SDCCmd}] - - -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.000 [get_ports {SDCCmd}] -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 6.000 [get_ports {SDCCmd}] - -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] 0.000 [get_ports SDCCLK] +set_output_delay -clock [get_clocks SPISDCClock] 0.000 [get_ports SDCCLK] #set_multicycle_path -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 10 From 121342f4ccd3a3b62d1783fe0d141a24df895c34 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 22 Jul 2024 16:12:06 -0500 Subject: [PATCH 109/163] Updated the verilog-ethernet repo to remove most of the warnings. Updated the fpga constraints so the ILA is more useful when using RVVI. --- addins/verilog-ethernet | 2 +- fpga/constraints/small-debug-rvvi.xdc | 43 ++++++++++----------------- src/rvvi/rvvisynth.sv | 2 +- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet index 43990ab4f..471394b80 160000 --- a/addins/verilog-ethernet +++ b/addins/verilog-ethernet @@ -1 +1 @@ -Subproject commit 43990ab4fd0c8d34dbc1be5cd8d4f3ed3e33f853 +Subproject commit 471394b80c95a4859cd55a0f253d5ea502371e98 diff --git a/fpga/constraints/small-debug-rvvi.xdc b/fpga/constraints/small-debug-rvvi.xdc index f8ebbfe0d..0441f4fa2 100644 --- a/fpga/constraints/small-debug-rvvi.xdc +++ b/fpga/constraints/small-debug-rvvi.xdc @@ -9,7 +9,7 @@ set_property C_ADV_TRIGGER true [get_debug_cores u_ila_0 ] set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0 ] set_property ALL_PROBE_SAME_MU_CNT 4 [get_debug_cores u_ila_0 ] create_debug_port u_ila_0 trig_in -create_debug_port u_ila_0 trig_in_ack +create_debug_port u_ila_0 trig_in_ack #set_property port_width 1 [get_debug_ports u_ila_0/trig_in] #set_property port_width 1 [get_debug_ports u_ila_0/trig_in_ack] #set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/trig_in] @@ -17,14 +17,14 @@ connect_debug_port u_ila_0/trig_in [get_nets IlaTrigger] #connect_debug_port u_ila_0/trig_in_ack [get_nets IlaTriggerAck] connect_debug_port u_ila_0/clk [get_nets CPUCLK] -set_property port_width 32 [get_debug_ports u_ila_0/probe0] +set_property port_width 64 [get_debug_ports u_ila_0/probe0] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0] -connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] +connect_debug_port u_ila_0/probe0 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe1] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1] -connect_debug_port u_ila_0/probe1 [get_nets [list rvvi_synth/RvviAxiWlast ]] +connect_debug_port u_ila_0/probe1 [get_nets [list wallypipelinedsoc/core/TrapM ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe2] @@ -32,50 +32,39 @@ set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2] connect_debug_port u_ila_0/probe2 [get_nets [list wallypipelinedsoc/core/InstrValidM ]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe3] +set_property port_width 32 [get_debug_ports u_ila_0/probe3] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3] -connect_debug_port u_ila_0/probe3 [get_nets [list {rvvi_synth/RvviAxiRlast}]] +connect_debug_port u_ila_0/probe3 [get_nets [list {wallypipelinedsoc/core/InstrM[0]} {wallypipelinedsoc/core/InstrM[1]} {wallypipelinedsoc/core/InstrM[2]} {wallypipelinedsoc/core/InstrM[3]} {wallypipelinedsoc/core/InstrM[4]} {wallypipelinedsoc/core/InstrM[5]} {wallypipelinedsoc/core/InstrM[6]} {wallypipelinedsoc/core/InstrM[7]} {wallypipelinedsoc/core/InstrM[8]} {wallypipelinedsoc/core/InstrM[9]} {wallypipelinedsoc/core/InstrM[10]} {wallypipelinedsoc/core/InstrM[11]} {wallypipelinedsoc/core/InstrM[12]} {wallypipelinedsoc/core/InstrM[13]} {wallypipelinedsoc/core/InstrM[14]} {wallypipelinedsoc/core/InstrM[15]} {wallypipelinedsoc/core/InstrM[16]} {wallypipelinedsoc/core/InstrM[17]} {wallypipelinedsoc/core/InstrM[18]} {wallypipelinedsoc/core/InstrM[19]} {wallypipelinedsoc/core/InstrM[20]} {wallypipelinedsoc/core/InstrM[21]} {wallypipelinedsoc/core/InstrM[22]} {wallypipelinedsoc/core/InstrM[23]} {wallypipelinedsoc/core/InstrM[24]} {wallypipelinedsoc/core/InstrM[25]} {wallypipelinedsoc/core/InstrM[26]} {wallypipelinedsoc/core/InstrM[27]} {wallypipelinedsoc/core/InstrM[28]} {wallypipelinedsoc/core/InstrM[29]} {wallypipelinedsoc/core/InstrM[30]} {wallypipelinedsoc/core/InstrM[31]} ]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe4] +set_property port_width 2 [get_debug_ports u_ila_0/probe4] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4] -connect_debug_port u_ila_0/probe4 [get_nets [list {rvvi_synth/RvviAxiRvalid}]] +connect_debug_port u_ila_0/probe4 [get_nets [list {wallypipelinedsoc/core/lsu/MemRWM[0]} {wallypipelinedsoc/core/lsu/MemRWM[1]} ]] create_debug_port u_ila_0 probe -set_property port_width 4 [get_debug_ports u_ila_0/probe5] +set_property port_width 64 [get_debug_ports u_ila_0/probe5] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5] -connect_debug_port u_ila_0/probe5 [get_nets [list {rvvi_synth/packetizer/CurrState[0]} {rvvi_synth/packetizer/CurrState[1]} {rvvi_synth/packetizer/CurrState[2]} {rvvi_synth/packetizer/CurrState[3]}]] +connect_debug_port u_ila_0/probe5 [get_nets [list {wallypipelinedsoc/core/lsu/IEUAdrM[0]} {wallypipelinedsoc/core/lsu/IEUAdrM[1]} {wallypipelinedsoc/core/lsu/IEUAdrM[2]} {wallypipelinedsoc/core/lsu/IEUAdrM[3]} {wallypipelinedsoc/core/lsu/IEUAdrM[4]} {wallypipelinedsoc/core/lsu/IEUAdrM[5]} {wallypipelinedsoc/core/lsu/IEUAdrM[6]} {wallypipelinedsoc/core/lsu/IEUAdrM[7]} {wallypipelinedsoc/core/lsu/IEUAdrM[8]} {wallypipelinedsoc/core/lsu/IEUAdrM[9]} {wallypipelinedsoc/core/lsu/IEUAdrM[10]} {wallypipelinedsoc/core/lsu/IEUAdrM[11]} {wallypipelinedsoc/core/lsu/IEUAdrM[12]} {wallypipelinedsoc/core/lsu/IEUAdrM[13]} {wallypipelinedsoc/core/lsu/IEUAdrM[14]} {wallypipelinedsoc/core/lsu/IEUAdrM[15]} {wallypipelinedsoc/core/lsu/IEUAdrM[16]} {wallypipelinedsoc/core/lsu/IEUAdrM[17]} {wallypipelinedsoc/core/lsu/IEUAdrM[18]} {wallypipelinedsoc/core/lsu/IEUAdrM[19]} {wallypipelinedsoc/core/lsu/IEUAdrM[20]} {wallypipelinedsoc/core/lsu/IEUAdrM[21]} {wallypipelinedsoc/core/lsu/IEUAdrM[22]} {wallypipelinedsoc/core/lsu/IEUAdrM[23]} {wallypipelinedsoc/core/lsu/IEUAdrM[24]} {wallypipelinedsoc/core/lsu/IEUAdrM[25]} {wallypipelinedsoc/core/lsu/IEUAdrM[26]} {wallypipelinedsoc/core/lsu/IEUAdrM[27]} {wallypipelinedsoc/core/lsu/IEUAdrM[28]} {wallypipelinedsoc/core/lsu/IEUAdrM[29]} {wallypipelinedsoc/core/lsu/IEUAdrM[30]} {wallypipelinedsoc/core/lsu/IEUAdrM[31]} {wallypipelinedsoc/core/lsu/IEUAdrM[32]} {wallypipelinedsoc/core/lsu/IEUAdrM[33]} {wallypipelinedsoc/core/lsu/IEUAdrM[34]} {wallypipelinedsoc/core/lsu/IEUAdrM[35]} {wallypipelinedsoc/core/lsu/IEUAdrM[36]} {wallypipelinedsoc/core/lsu/IEUAdrM[37]} {wallypipelinedsoc/core/lsu/IEUAdrM[38]} {wallypipelinedsoc/core/lsu/IEUAdrM[39]} {wallypipelinedsoc/core/lsu/IEUAdrM[40]} {wallypipelinedsoc/core/lsu/IEUAdrM[41]} {wallypipelinedsoc/core/lsu/IEUAdrM[42]} {wallypipelinedsoc/core/lsu/IEUAdrM[43]} {wallypipelinedsoc/core/lsu/IEUAdrM[44]} {wallypipelinedsoc/core/lsu/IEUAdrM[45]} {wallypipelinedsoc/core/lsu/IEUAdrM[46]} {wallypipelinedsoc/core/lsu/IEUAdrM[47]} {wallypipelinedsoc/core/lsu/IEUAdrM[48]} {wallypipelinedsoc/core/lsu/IEUAdrM[49]} {wallypipelinedsoc/core/lsu/IEUAdrM[50]} {wallypipelinedsoc/core/lsu/IEUAdrM[51]} {wallypipelinedsoc/core/lsu/IEUAdrM[52]} {wallypipelinedsoc/core/lsu/IEUAdrM[53]} {wallypipelinedsoc/core/lsu/IEUAdrM[54]} {wallypipelinedsoc/core/lsu/IEUAdrM[55]} {wallypipelinedsoc/core/lsu/IEUAdrM[56]} {wallypipelinedsoc/core/lsu/IEUAdrM[57]} {wallypipelinedsoc/core/lsu/IEUAdrM[58]} {wallypipelinedsoc/core/lsu/IEUAdrM[59]} {wallypipelinedsoc/core/lsu/IEUAdrM[60]} {wallypipelinedsoc/core/lsu/IEUAdrM[61]} {wallypipelinedsoc/core/lsu/IEUAdrM[62]} {wallypipelinedsoc/core/lsu/IEUAdrM[63]} ]] create_debug_port u_ila_0 probe set_property port_width 64 [get_debug_ports u_ila_0/probe6] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6] -connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/PCM[0]} {wallypipelinedsoc/core/PCM[1]} {wallypipelinedsoc/core/PCM[2]} {wallypipelinedsoc/core/PCM[3]} {wallypipelinedsoc/core/PCM[4]} {wallypipelinedsoc/core/PCM[5]} {wallypipelinedsoc/core/PCM[6]} {wallypipelinedsoc/core/PCM[7]} {wallypipelinedsoc/core/PCM[8]} {wallypipelinedsoc/core/PCM[9]} {wallypipelinedsoc/core/PCM[10]} {wallypipelinedsoc/core/PCM[11]} {wallypipelinedsoc/core/PCM[12]} {wallypipelinedsoc/core/PCM[13]} {wallypipelinedsoc/core/PCM[14]} {wallypipelinedsoc/core/PCM[15]} {wallypipelinedsoc/core/PCM[16]} {wallypipelinedsoc/core/PCM[17]} {wallypipelinedsoc/core/PCM[18]} {wallypipelinedsoc/core/PCM[19]} {wallypipelinedsoc/core/PCM[20]} {wallypipelinedsoc/core/PCM[21]} {wallypipelinedsoc/core/PCM[22]} {wallypipelinedsoc/core/PCM[23]} {wallypipelinedsoc/core/PCM[24]} {wallypipelinedsoc/core/PCM[25]} {wallypipelinedsoc/core/PCM[26]} {wallypipelinedsoc/core/PCM[27]} {wallypipelinedsoc/core/PCM[28]} {wallypipelinedsoc/core/PCM[29]} {wallypipelinedsoc/core/PCM[30]} {wallypipelinedsoc/core/PCM[31]} {wallypipelinedsoc/core/PCM[32]} {wallypipelinedsoc/core/PCM[33]} {wallypipelinedsoc/core/PCM[34]} {wallypipelinedsoc/core/PCM[35]} {wallypipelinedsoc/core/PCM[36]} {wallypipelinedsoc/core/PCM[37]} {wallypipelinedsoc/core/PCM[38]} {wallypipelinedsoc/core/PCM[39]} {wallypipelinedsoc/core/PCM[40]} {wallypipelinedsoc/core/PCM[41]} {wallypipelinedsoc/core/PCM[42]} {wallypipelinedsoc/core/PCM[43]} {wallypipelinedsoc/core/PCM[44]} {wallypipelinedsoc/core/PCM[45]} {wallypipelinedsoc/core/PCM[46]} {wallypipelinedsoc/core/PCM[47]} {wallypipelinedsoc/core/PCM[48]} {wallypipelinedsoc/core/PCM[49]} {wallypipelinedsoc/core/PCM[50]} {wallypipelinedsoc/core/PCM[51]} {wallypipelinedsoc/core/PCM[52]} {wallypipelinedsoc/core/PCM[53]} {wallypipelinedsoc/core/PCM[54]} {wallypipelinedsoc/core/PCM[55]} {wallypipelinedsoc/core/PCM[56]} {wallypipelinedsoc/core/PCM[57]} {wallypipelinedsoc/core/PCM[58]} {wallypipelinedsoc/core/PCM[59]} {wallypipelinedsoc/core/PCM[60]} {wallypipelinedsoc/core/PCM[61]} {wallypipelinedsoc/core/PCM[62]} {wallypipelinedsoc/core/PCM[63]} ]] +connect_debug_port u_ila_0/probe6 [get_nets [list {wallypipelinedsoc/core/lsu/ReadDataM[0]} {wallypipelinedsoc/core/lsu/ReadDataM[1]} {wallypipelinedsoc/core/lsu/ReadDataM[2]} {wallypipelinedsoc/core/lsu/ReadDataM[3]} {wallypipelinedsoc/core/lsu/ReadDataM[4]} {wallypipelinedsoc/core/lsu/ReadDataM[5]} {wallypipelinedsoc/core/lsu/ReadDataM[6]} {wallypipelinedsoc/core/lsu/ReadDataM[7]} {wallypipelinedsoc/core/lsu/ReadDataM[8]} {wallypipelinedsoc/core/lsu/ReadDataM[9]} {wallypipelinedsoc/core/lsu/ReadDataM[10]} {wallypipelinedsoc/core/lsu/ReadDataM[11]} {wallypipelinedsoc/core/lsu/ReadDataM[12]} {wallypipelinedsoc/core/lsu/ReadDataM[13]} {wallypipelinedsoc/core/lsu/ReadDataM[14]} {wallypipelinedsoc/core/lsu/ReadDataM[15]} {wallypipelinedsoc/core/lsu/ReadDataM[16]} {wallypipelinedsoc/core/lsu/ReadDataM[17]} {wallypipelinedsoc/core/lsu/ReadDataM[18]} {wallypipelinedsoc/core/lsu/ReadDataM[19]} {wallypipelinedsoc/core/lsu/ReadDataM[20]} {wallypipelinedsoc/core/lsu/ReadDataM[21]} {wallypipelinedsoc/core/lsu/ReadDataM[22]} {wallypipelinedsoc/core/lsu/ReadDataM[23]} {wallypipelinedsoc/core/lsu/ReadDataM[24]} {wallypipelinedsoc/core/lsu/ReadDataM[25]} {wallypipelinedsoc/core/lsu/ReadDataM[26]} {wallypipelinedsoc/core/lsu/ReadDataM[27]} {wallypipelinedsoc/core/lsu/ReadDataM[28]} {wallypipelinedsoc/core/lsu/ReadDataM[29]} {wallypipelinedsoc/core/lsu/ReadDataM[30]} {wallypipelinedsoc/core/lsu/ReadDataM[31]} {wallypipelinedsoc/core/lsu/ReadDataM[32]} {wallypipelinedsoc/core/lsu/ReadDataM[33]} {wallypipelinedsoc/core/lsu/ReadDataM[34]} {wallypipelinedsoc/core/lsu/ReadDataM[35]} {wallypipelinedsoc/core/lsu/ReadDataM[36]} {wallypipelinedsoc/core/lsu/ReadDataM[37]} {wallypipelinedsoc/core/lsu/ReadDataM[38]} {wallypipelinedsoc/core/lsu/ReadDataM[39]} {wallypipelinedsoc/core/lsu/ReadDataM[40]} {wallypipelinedsoc/core/lsu/ReadDataM[41]} {wallypipelinedsoc/core/lsu/ReadDataM[42]} {wallypipelinedsoc/core/lsu/ReadDataM[43]} {wallypipelinedsoc/core/lsu/ReadDataM[44]} {wallypipelinedsoc/core/lsu/ReadDataM[45]} {wallypipelinedsoc/core/lsu/ReadDataM[46]} {wallypipelinedsoc/core/lsu/ReadDataM[47]} {wallypipelinedsoc/core/lsu/ReadDataM[48]} {wallypipelinedsoc/core/lsu/ReadDataM[49]} {wallypipelinedsoc/core/lsu/ReadDataM[50]} {wallypipelinedsoc/core/lsu/ReadDataM[51]} {wallypipelinedsoc/core/lsu/ReadDataM[52]} {wallypipelinedsoc/core/lsu/ReadDataM[53]} {wallypipelinedsoc/core/lsu/ReadDataM[54]} {wallypipelinedsoc/core/lsu/ReadDataM[55]} {wallypipelinedsoc/core/lsu/ReadDataM[56]} {wallypipelinedsoc/core/lsu/ReadDataM[57]} {wallypipelinedsoc/core/lsu/ReadDataM[58]} {wallypipelinedsoc/core/lsu/ReadDataM[59]} {wallypipelinedsoc/core/lsu/ReadDataM[60]} {wallypipelinedsoc/core/lsu/ReadDataM[61]} {wallypipelinedsoc/core/lsu/ReadDataM[62]} {wallypipelinedsoc/core/lsu/ReadDataM[63]} ]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe7] +set_property port_width 64 [get_debug_ports u_ila_0/probe7] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7] -connect_debug_port u_ila_0/probe7 [get_nets [list {rvvi_synth/RvviAxiWvalid}]] +connect_debug_port u_ila_0/probe7 [get_nets [list {wallypipelinedsoc/core/lsu/WriteDataM[0]} {wallypipelinedsoc/core/lsu/WriteDataM[1]} {wallypipelinedsoc/core/lsu/WriteDataM[2]} {wallypipelinedsoc/core/lsu/WriteDataM[3]} {wallypipelinedsoc/core/lsu/WriteDataM[4]} {wallypipelinedsoc/core/lsu/WriteDataM[5]} {wallypipelinedsoc/core/lsu/WriteDataM[6]} {wallypipelinedsoc/core/lsu/WriteDataM[7]} {wallypipelinedsoc/core/lsu/WriteDataM[8]} {wallypipelinedsoc/core/lsu/WriteDataM[9]} {wallypipelinedsoc/core/lsu/WriteDataM[10]} {wallypipelinedsoc/core/lsu/WriteDataM[11]} {wallypipelinedsoc/core/lsu/WriteDataM[12]} {wallypipelinedsoc/core/lsu/WriteDataM[13]} {wallypipelinedsoc/core/lsu/WriteDataM[14]} {wallypipelinedsoc/core/lsu/WriteDataM[15]} {wallypipelinedsoc/core/lsu/WriteDataM[16]} {wallypipelinedsoc/core/lsu/WriteDataM[17]} {wallypipelinedsoc/core/lsu/WriteDataM[18]} {wallypipelinedsoc/core/lsu/WriteDataM[19]} {wallypipelinedsoc/core/lsu/WriteDataM[20]} {wallypipelinedsoc/core/lsu/WriteDataM[21]} {wallypipelinedsoc/core/lsu/WriteDataM[22]} {wallypipelinedsoc/core/lsu/WriteDataM[23]} {wallypipelinedsoc/core/lsu/WriteDataM[24]} {wallypipelinedsoc/core/lsu/WriteDataM[25]} {wallypipelinedsoc/core/lsu/WriteDataM[26]} {wallypipelinedsoc/core/lsu/WriteDataM[27]} {wallypipelinedsoc/core/lsu/WriteDataM[28]} {wallypipelinedsoc/core/lsu/WriteDataM[29]} {wallypipelinedsoc/core/lsu/WriteDataM[30]} {wallypipelinedsoc/core/lsu/WriteDataM[31]} {wallypipelinedsoc/core/lsu/WriteDataM[32]} {wallypipelinedsoc/core/lsu/WriteDataM[33]} {wallypipelinedsoc/core/lsu/WriteDataM[34]} {wallypipelinedsoc/core/lsu/WriteDataM[35]} {wallypipelinedsoc/core/lsu/WriteDataM[36]} {wallypipelinedsoc/core/lsu/WriteDataM[37]} {wallypipelinedsoc/core/lsu/WriteDataM[38]} {wallypipelinedsoc/core/lsu/WriteDataM[39]} {wallypipelinedsoc/core/lsu/WriteDataM[40]} {wallypipelinedsoc/core/lsu/WriteDataM[41]} {wallypipelinedsoc/core/lsu/WriteDataM[42]} {wallypipelinedsoc/core/lsu/WriteDataM[43]} {wallypipelinedsoc/core/lsu/WriteDataM[44]} {wallypipelinedsoc/core/lsu/WriteDataM[45]} {wallypipelinedsoc/core/lsu/WriteDataM[46]} {wallypipelinedsoc/core/lsu/WriteDataM[47]} {wallypipelinedsoc/core/lsu/WriteDataM[48]} {wallypipelinedsoc/core/lsu/WriteDataM[49]} {wallypipelinedsoc/core/lsu/WriteDataM[50]} {wallypipelinedsoc/core/lsu/WriteDataM[51]} {wallypipelinedsoc/core/lsu/WriteDataM[52]} {wallypipelinedsoc/core/lsu/WriteDataM[53]} {wallypipelinedsoc/core/lsu/WriteDataM[54]} {wallypipelinedsoc/core/lsu/WriteDataM[55]} {wallypipelinedsoc/core/lsu/WriteDataM[56]} {wallypipelinedsoc/core/lsu/WriteDataM[57]} {wallypipelinedsoc/core/lsu/WriteDataM[58]} {wallypipelinedsoc/core/lsu/WriteDataM[59]} {wallypipelinedsoc/core/lsu/WriteDataM[60]} {wallypipelinedsoc/core/lsu/WriteDataM[61]} {wallypipelinedsoc/core/lsu/WriteDataM[62]} {wallypipelinedsoc/core/lsu/WriteDataM[63]} ]] create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe8] +set_property port_width 32 [get_debug_ports u_ila_0/probe8] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8] -connect_debug_port u_ila_0/probe8 [get_nets [list {RVVIStall}]] +connect_debug_port u_ila_0/probe8 [get_nets [list {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][0]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][1]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][2]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][3]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][4]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][5]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][6]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][7]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][8]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][9]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][10]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][11]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][12]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][13]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][14]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][15]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][16]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][17]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][18]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][19]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][20]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][21]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][22]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][23]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][24]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][25]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][26]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][27]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][28]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][29]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][30]} {wallypipelinedsoc/core/priv.priv/csr/HPMCOUNTER_REGW[0][31]} ]] create_debug_port u_ila_0 probe set_property port_width 1 [get_debug_ports u_ila_0/probe9] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe9] -connect_debug_port u_ila_0/probe9 [get_nets [list {rvvi_synth/valid}]] - -create_debug_port u_ila_0 probe -set_property port_width 1 [get_debug_ports u_ila_0/probe10] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe10] -connect_debug_port u_ila_0/probe10 [get_nets [list {rvvi_synth/RvviAxiWready}]] - -create_debug_port u_ila_0 probe -set_property port_width 3 [get_debug_ports u_ila_0/probe11] -set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe11] -connect_debug_port u_ila_0/probe11 [get_nets [list {rvvi_synth/triggergen/CurrState[0]} {rvvi_synth/triggergen/CurrState[1]} {rvvi_synth/triggergen/CurrState[2]}]] - +connect_debug_port u_ila_0/probe9 [get_nets [list {RVVIStall}]] # the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock. #connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk] diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index cbf7c30bf..5ee8b8c52 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -44,7 +44,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, input logic GPRWen, FPRWen, input logic [4:0] GPRAddr, FPRAddr, input logic [P.XLEN-1:0] GPRValue, FPRValue, - input logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0], + input var logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0], output logic valid, output logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi ); From b05052311f095a7e7021a3d1d5dd391dfcd1e5b0 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Mon, 22 Jul 2024 16:57:04 -0500 Subject: [PATCH 110/163] Added sd_cmd and utility SPI functions. --- fpga/zsbl/sd.c | 68 ++++++++++++++++++++++++++++++++++-- fpga/zsbl/sd.h | 3 +- fpga/zsbl/spi.c | 91 ++++++++++++++++++++++++++++++++++--------------- fpga/zsbl/spi.h | 53 +++++++++++++++++----------- 4 files changed, 164 insertions(+), 51 deletions(-) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 8781dd5c3..aacea0db9 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -12,6 +12,7 @@ uint8_t crc7(uint8_t prev, uint8_t in) { return remainder & 0xff; } +// Need to check this. This could be wrong as well. uint16_t crc16(uint16_t crc, uint8_t data) { // CRC polynomial 0x11021 crc = (uint8_t)(crc >> 8) | (crc << 8); @@ -22,13 +23,74 @@ uint16_t crc16(uint16_t crc, uint8_t data) { return crc; } -uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { - spi_send_byte +uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { + uint8_t response_len; + uint8_t i; + uint64_t r; + uint8_t rbyte; + + switch (cmd) { + case 0: + response_len = 1; + break; + case 8: + response_len = 7 + break; + default: + response_len = 1; + break; + } + + // Make interrupt pending after response fifo receives the correct + // response length. + write_reg(SPI_RXMARK, response_len); + + // Write all 6 bytes into transfer fifo + spi_sendbyte(0x40 | cmd); + spi_sendbyte(arg >> 24); + spi_sendbyte(arg >> 16); + spi_sendbyte(arg >> 8); + spi_sendbyte(arg); + spi_sendbyte(crc); + + // Wait for command to send + // The Transfer IP bit should go high when the txFIFO is empty + // while(!(read_reg(SPI_IP) & 1)) {} + waittx(); + + // Read the dummy rxFIFO entries to move the head back to the tail + for (i = 0; i < 6; i++) { + spi_readbyte(); + } + + // Send "dummy signals". Since SPI is duplex, + // useless bytes must be transferred + for (i = 0; i < response_len; i++) { + spi_sendbyte(0xFF); + } + + // Wait for transfer fifo again + waittx(); + + // Read rxfifo response + for (i = 0; i < response_len; i++) { + rbyte = spi_readbyte(); + r = r | (rbyte << ((response_len - 1 - i)*8)); + } + + return r; } +#define cmd0() sd_cmd( 0, 0x00000000, 0x95) +#define cmd8() sd_cmd( 8, 0x000001aa, 0x87) +// CMD55 has to be sent before ACMD41 (it means the next command is +// application specific) +#define cmd55() sd_cmd(55, 0x00000000, 0x65) +#defube acmd41() sd_cmd(41, 0x40000000, 0x77) + void init_sd(){ init_spi(); - + cmd0() } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index b1b27db14..f08941364 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -4,6 +4,5 @@ uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); -uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); +uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); void init_sd(); - diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index bf6d629b4..c812327f4 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -1,50 +1,87 @@ +/////////////////////////////////////////////////////////////////////// +// spi.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: SPI Controller API for bootloader +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include "spi.h" -void write_reg(uintptr_t addr, uint32_t value) { +// Write to a register +inline void write_reg(uintptr_t addr, uint32_t value) { volatile uint32_t * loc = (volatile uint32_t *) addr; *loc = value; } -void read_red(uintptr_t addr) { +// Read a register +inline void read_reg(uintptr_t addr) { return *(volatile uint32_t *) addr; } +// Queues a single byte in the transfer fifo +inline void spi_sendbyte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); +} + +inline uint8_t spi_readbyte() { + return read_reg(SPI_RXDATA); +} + +inline void waittx() { + while(!(read_reg(SPI_IP) & 1)) {} +} + +inline void waitrx() { + while(read_reg(SPI_IP) & 2)) {} +} + + // Initialize Sifive FU540 based SPI Controller void spi_init() { - // Disable interrupts by default - // write_reg(SPI_IE, 0); + // Enable interrupts + write_reg(SPI_IE, 0x3); + // Set TXMARK to 1. If the number of entries is < 1 + // IP's txwm field will go high. + // Set RXMARK to 0. If the number of entries is > 0 + // IP's rwxm field will go high. write_reg(SPI_TXMARK, 1); write_reg(SPI_RXMARK, 0); + // Set Delay 0 to default write_reg(SPI_DELAY0, SIFIVE_SPI_DELAY0_CSSCK(1) | SIFIVE_SPI_DELAY0_SCKCS(1)); + // Set Delay 1 to default write_reg(SPI_DELAY1, SIFIVE_SPI_DELAY1_INTERCS(1) | SIFIVE_SPI_DELAY1_INTERXFR(0)); + + // Initialize the SPI controller clock to + // div = (20MHz/(2*400kHz)) - 1 = 24 = 0x18 + write_reg(SPI_SCKDIV, 0x18); } - -// Sends and receives a single byte -uint8_t spi_send_byte(uint8_t byte) { - // Write byte to transfer fifo - write_reg(SPI_TXDATA, byte); - - /* Not sure how necessary this is. Will keep commented for now. - // Wait a decent amount of time for data to send - for (int i = 0; i < 100; i++) { - __asm__ volatile("nop"); - } - */ - - // Wait for data to come into receive fifo - while (read_reg(SPI_IP) != 2) {} - - // Read received data - result = read_reg(SPI_RXDATA); - - // Return result - return result; -} - diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index 6bae450ae..a035f0ab5 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -4,26 +4,28 @@ #include <stdint.h> +#define SPI_BASE 0x13000 /* Base address of SPI device used for SDC */ + /* register offsets */ -#define SPI_SCKDIV 0x00 /* Serial clock divisor */ -#define SPI_SCKMODE 0x04 /* Serial clock mode */ -#define SPI_CSID 0x10 /* Chip select ID */ -#define SPI_CSDEF 0x14 /* Chip select default */ -#define SPI_CSMODE 0x18 /* Chip select mode */ -#define SPI_DELAY0 0x28 /* Delay control 0 */ -#define SPI_DELAY1 0x2c /* Delay control 1 */ -#define SPI_FMT 0x40 /* Frame format */ -#define SPI_TXDATA 0x48 /* Tx FIFO data */ -#define SPI_RXDATA 0x4c /* Rx FIFO data */ -#define SPI_TXMARK 0x50 /* Tx FIFO [<35;39;29Mwatermark */ -#define SPI_RXMARK 0x54 /* Rx FIFO watermark */ +#define SPI_SCKDIV SPI_BASE + 0x00 /* Serial clock divisor */ +#define SPI_SCKMODE SPI_BASE + 0x04 /* Serial clock mode */ +#define SPI_CSID SPI_BASE + 0x10 /* Chip select ID */ +#define SPI_CSDEF SPI_BASE + 0x14 /* Chip select default */ +#define SPI_CSMODE SPI_BASE + 0x18 /* Chip select mode */ +#define SPI_DELAY0 SPI_BASE + 0x28 /* Delay control 0 */ +#define SPI_DELAY1 SPI_BASE + 0x2c /* Delay control 1 */ +#define SPI_FMT SPI_BASE + 0x40 /* Frame format */ +#define SPI_TXDATA SPI_BASE + 0x48 /* Tx FIFO data */ +#define SPI_RXDATA SPI_BASE + 0x4c /* Rx FIFO data */ +#define SPI_TXMARK SPI_BASE + 0x50 /* Tx FIFO [<35;39;29Mwatermark */ +#define SPI_RXMARK SPI_BASE + 0x54 /* Rx FIFO watermark */ /* Non-implemented -#define SPI_FCTRL 0x60 // SPI flash interface control -#define SPI_FFMT 0x64 // SPI flash instruction format +#define SPI_FCTRL SPI_BASE + 0x60 // SPI flash interface control +#define SPI_FFMT SPI_BASE + 0x64 // SPI flash instruction format */ -#define SPI_IE 0x70 /* Interrupt Enable Register */ -#define SPI_IP 0x74 /* Interrupt Pendings Register */ +#define SPI_IE SPI_BASE + 0x70 /* Interrupt Enable Register */ +#define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */ /* delay0 bits */ #define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) @@ -37,9 +39,22 @@ #define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) #define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) -void write_reg(uintptr_t addr, uint32_t value); -uint32_t read_reg(uintptr_t addr); -uint8_t spi_send_byte(uint8_t byte); +/* csmode bits */ +#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U +#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U +#define SIFIVE_SPI_CSMODE_MODE_OFF 3U + + +#define WAITTX while(!(read_reg(SPI_IP) & 1) {} +#define WAITRX while(read_reg(SPI_IP) & 2) {} + +inline void write_reg(uintptr_t addr, uint32_t value); +inline uint32_t read_reg(uintptr_t addr); +inline void spi_sendbyte(uint8_t byte); +inline void waittx(); +inline void waitrx(); +uint8_t spi_txrx(uint8_t byte); +inline uint8_t spi_readbyte(); void spi_init(); From 8ca565ed53db8bd59e41c4bd434e773d13b187f3 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Mon, 22 Jul 2024 17:44:04 -0500 Subject: [PATCH 111/163] Updated for a better ILA rvvi debugger. --- config/derivlist.txt | 4 ++-- fpga/constraints/small-debug-rvvi.xdc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/derivlist.txt b/config/derivlist.txt index 01ad315e5..048adcb21 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -57,9 +57,9 @@ EXT_MEM_RANGE 64'h0FFFFFFF SDC_SUPPORTED 1 PLIC_SDC_ID 32'd20 BPRED_SIZE 32'd12 -RVVI_SYNTH_SUPPORTED 0 +RVVI_SYNTH_SUPPORTED 1 RVVI_INIT_TIME_OUT 32'd100000000 -RVVI_PACKET_DELAY 32'd350 +RVVI_PACKET_DELAY 32'd400 # The syn configurations are trimmed down for faster synthesis. diff --git a/fpga/constraints/small-debug-rvvi.xdc b/fpga/constraints/small-debug-rvvi.xdc index 0441f4fa2..629cde561 100644 --- a/fpga/constraints/small-debug-rvvi.xdc +++ b/fpga/constraints/small-debug-rvvi.xdc @@ -1,5 +1,5 @@ create_debug_core u_ila_0 ila -set_property C_DATA_DEPTH 8192 [get_debug_cores u_ila_0] +set_property C_DATA_DEPTH 4096 [get_debug_cores u_ila_0] set_property C_TRIGIN_EN true [get_debug_cores u_ila_0] set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0] From a4a0a10879733874821032860cfeea7093a4f096 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Tue, 23 Jul 2024 04:38:13 -0700 Subject: [PATCH 112/163] Increased covergen.py functional coverage to 87.6% --- bin/regression-wally | 2 +- tests/testgen/covergen.py | 131 ++++++++++++++++++++++++-------- tests/testgen/covergen_footer.S | 6 ++ 3 files changed, 105 insertions(+), 34 deletions(-) diff --git a/bin/regression-wally b/bin/regression-wally index 5a374b2d9..3040f584b 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -288,7 +288,7 @@ def addLockstepTestsByDir(dir, config, sim): for file in os.listdir(dir): if file.endswith(".elf"): fullfile = os.path.join(dir, file) - sim_log = sim_logdir + config + "_" + file + sim_log = sim_logdir + config + "_" + file + ".log" grepstring = "" tc = TestCase( name=file, diff --git a/tests/testgen/covergen.py b/tests/testgen/covergen.py index 06cf1bb83..2bf5f6a63 100755 --- a/tests/testgen/covergen.py +++ b/tests/testgen/covergen.py @@ -48,32 +48,48 @@ def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n" elif (test in shiftitype): lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" - lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\n" + if (test in shiftiwtype): + lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, 32) + " # perform operation\n" + else: + lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\n" elif (test in itype): lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n" elif (test in loaditype):#["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] - pass - #lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" - #lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # add immediate to lower part of rs1\n" - #lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" + if (rs1 != 0): + lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" + lines = lines + "la x" + str(rs1) + ", scratch" + " # base address \n" + lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # sub immediate from rs1 to counter offset\n" + if (xlen == 32): + storeop = "sw" + else: + storeop = "sd" + lines = lines + storeop + " x" + str(rs2) + ", " + signedImm12(immval) +" (x" + str(rs1) + ") # store value to put someting in memory\n" + lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" +# lines = lines + test + " x" + str(rd) + ", 0(x" + str(rs1) + ") # perform operation\n" elif (test in stype):#["sb", "sh", "sw", "sd"] - #lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" - #lines = lines + test + " x" + str(rs2) + ", " "0(x" + str(rs1) + ") # perform operation \n" - #print("Error: %s type not implemented yet" % test) - pass + if (rs1 != 0): + if (rs2 == rs1): # make sure registers are different so they don't conflict + rs2 = (rs1 + 1) % 32 + if (rs2 == 0): + rs2 = 1 + lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" + lines = lines + "la x" + str(rs1) + ", scratch" + " # base address \n" + lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # sub immediate from rs1 to counter offset\n" + lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" elif (test in btype):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] - if (randint(1,100) > 50): - rs1val = rs2val - lines = lines + "# same values in both registers\n" - lines = lines + "nop\n" - lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" - lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" - lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_sb_types_" + str(immval) + "+4" + " # perform operation \n" - lines = lines + "addi x0, x1, 1\n" - lines = lines + "some_label_for_sb_types_" + str(immval) + ":\n" - lines = lines + "addi x0, x2, 2\n" - lines = lines + "nop\nnop\nnop\nnop\nnop\n" + for same in range(2): + if (same): + rs1val = rs2val + lines = lines + "# same values in both registers\n" + lines = lines + "nop\n" + lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" + lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n" + lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_btype_" + str(immval) + str(same) + " # perform operation \n" + lines = lines + "addi x0, x1, 1\n" + lines = lines + "some_label_for_btype_" + str(immval)+ str(same) + ":\n" + lines = lines + "addi x0, x2, 2\n" + lines = lines + "nop\nnop\nnop\nnop\nnop\n" elif (test in jtype):#["jal"] lines = lines + "jal x" + str(rd) + ", 1f # perform operation\n" lines = lines + "nop\n" @@ -151,7 +167,7 @@ def make_rd_rs1_rs2(test, xlen): def make_rs1_rs2(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() - desc = "cmp_rd_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")" + desc = "cmp_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")" writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, xlen) def make_rs1_maxvals(test, xlen): @@ -171,15 +187,15 @@ def make_rd_maxvals(test, xlen): # rs1 = 0, rs2 = v, others are random [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" - writeCovVector(desc, rs1, 0, rd, v, rs2val, immval, rdval, test, xlen) + writeCovVector(desc, rs1, 0, rd, v, rs2val, 0, rdval, test, xlen) # rs1, rs2 = v, others are random [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" - writeCovVector(desc, rs1, rs2, rd, v, v, immval, rdval, test, xlen) + writeCovVector(desc, rs1, rs2, rd, v, v, v, rdval, test, xlen) # rs1 = all 1s, rs2 = v, others are random [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")" - writeCovVector(desc, rs1, rs2, rd, -1, v, immval, rdval, test, xlen) + writeCovVector(desc, rs1, rs2, rd, v, -1, -1, rdval, test, xlen) def make_rd_rs1_eqval(test, xlen): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() @@ -245,6 +261,53 @@ def make_imm_zero(test, xlen): desc = "cp_imm_zero" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, 0, rdval, test, xlen) +def make_j_imm_ones_zeros(test, xlen): + for align in range(2,19): + lines = "\n# Testcase cp_imm_ones_zeros " + str(align) + "\n" + lines = lines + "li x1, " + formatstr.format(randint(0, 2**xlen-1)) + "\n" + lines = lines + "jal x20, 1f # jump to aligned address to stress immediate\n" + lines = lines + ".align " + str(align) + "\n" + lines = lines + "1:\n" + f.write(lines) + +def make_offset(test, xlen): + if (test in btype): + lines = "\n# Testcase cp_offset\n" + lines = lines + "j 2f # jump past backward branch target\n" + lines = lines + "1: j 3f # backward branch target: jump past backward branch\n" + lines = lines + "2: " + test + " x0, x0, 1b # backward branch\n" + lines = lines + "3: nop # done with sequence\n" + f.write(lines) + +def make_mem_hazard(test, xlen): + lines = "\n# Testcase mem_hazard (no dependency)\n" + lines = lines + "la x1, scratch\n" + lines = lines + test + " x2, 0(x1)\n" + f.write(lines) + +def make_cr_rs1_imm(test, xlen): + desc = "cp_cr_rs1_imm" + [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() + for s1 in range(2): + for s2 in range(3): + if (s1): + rs1v = -abs(rs1val) + else: + rs1v = abs(rs1val) + if (s2 == 0): + immv = 0 + elif (s2 == 1): + immv = abs(immval) + else: + immv = -abs(immval) + writeCovVector(desc, rs1, rs2, rd, rs1v, rs2val, immv, rdval, test, xlen) + +def make_imm_shift(test, xlen): + desc = "cp_imm_shift" + for shift in range(0, xlen): + [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, shift, rdval, test, xlen) + def write_tests(coverpoints, test, xlen): for coverpoint in coverpoints: if (coverpoint == "cp_asm_count"): @@ -298,23 +361,24 @@ def write_tests(coverpoints, test, xlen): elif (coverpoint == "cp_imm_sign"): make_imm_zero(test, xlen) elif (coverpoint == "cr_rs1_imm"): - pass #TODO (not if crosses are not needed) + make_cr_rs1_imm(test, xlen) elif (coverpoint == "cp_imm_ones_zeros"): - pass #TODO + if (test in jtype): + make_j_imm_ones_zeros(test, xlen) elif (coverpoint == "cp_mem_hazard"): - pass #TODO + make_mem_hazard(test, xlen) elif (coverpoint == "cp_imm_zero"): make_imm_zero(test, xlen) elif (coverpoint == "cp_mem_unaligned"): - pass #TODO + pass # seems this should be part of privileged tests elif (coverpoint == "cp_offset"): - pass #TODO + make_offset(test, xlen) elif (coverpoint == "cr_nord_rs1_rs2"): pass #TODO (not if crosses are not needed) elif (coverpoint == "cp_imm_shift"): - pass #TODO + make_imm_shift(test, xlen) elif (coverpoint == "cp_rd_boolean"): - pass #TODO + pass # covered by other generators else: print("Warning: " + coverpoint + " not implemented yet for " + test) @@ -352,8 +416,9 @@ rtype = ["add", "sub", "sll", "slt", "sltu", "xor", "srl", "sra", "or", "and", "mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu", "mulw", "divw", "divuw", "remw", "remuw"] loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] -shiftitype = ["slli", "srli", "srai"] -itype = ["addi", "slti", "sltiu", "xori", "ori", "andi"] +shiftitype = ["slli", "srli", "srai", "slliw", "srliw", "sraiw"] +shiftiwtype = ["slliw", "srliw", "sraiw"] +itype = ["addi", "slti", "sltiu", "xori", "ori", "andi", "addiw"] stype = ["sb", "sh", "sw", "sd"] btype = ["beq", "bne", "blt", "bge", "bltu", "bgeu"] jtype = ["jal"] diff --git a/tests/testgen/covergen_footer.S b/tests/testgen/covergen_footer.S index 2e4abbbfc..9da7e65af 100644 --- a/tests/testgen/covergen_footer.S +++ b/tests/testgen/covergen_footer.S @@ -2,4 +2,10 @@ self_loop: j self_loop +.data + +.align 4 +scratch: + .bss 8 + .end From bb74a0f96b9ad3239385e1ba814844e273e345b9 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 12:23:04 -0500 Subject: [PATCH 113/163] Resolved more lint errors in the rvvi synthesized hardware. --- src/rvvi/csrindextoaddr.sv | 77 +++++++++++++++++++++++++++++++++++++ src/rvvi/packetizer.sv | 2 +- src/wally/csrindextoaddr.sv | 77 ------------------------------------- 3 files changed, 78 insertions(+), 78 deletions(-) create mode 100644 src/rvvi/csrindextoaddr.sv delete mode 100644 src/wally/csrindextoaddr.sv diff --git a/src/rvvi/csrindextoaddr.sv b/src/rvvi/csrindextoaddr.sv new file mode 100644 index 000000000..0a843f491 --- /dev/null +++ b/src/rvvi/csrindextoaddr.sv @@ -0,0 +1,77 @@ +/////////////////////////////////////////// +// csrindextoaddr.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Created: 24 January 2024 +// Modified: 24 January 2024 +// +// Purpose: Converts the rvvi CSR index into the CSR address +// +// Documentation: +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module csrindextoaddr #(parameter TOTAL_CSRS = 36) ( + input logic [TOTAL_CSRS-1:0] CSRWen, + output logic [11:0] CSRAddr); + + always_comb begin + case(CSRWen) + 36'h0_0000_0000: CSRAddr = 12'h000; + 36'h0_0000_0001: CSRAddr = 12'h300; + 36'h0_0000_0002: CSRAddr = 12'h310; + 36'h0_0000_0004: CSRAddr = 12'h305; + 36'h0_0000_0008: CSRAddr = 12'h341; + 36'h0_0000_0010: CSRAddr = 12'h306; + 36'h0_0000_0020: CSRAddr = 12'h320; + 36'h0_0000_0040: CSRAddr = 12'h302; + 36'h0_0000_0080: CSRAddr = 12'h303; + 36'h0_0000_0100: CSRAddr = 12'h344; + 36'h0_0000_0200: CSRAddr = 12'h304; + 36'h0_0000_0400: CSRAddr = 12'h301; + 36'h0_0000_0800: CSRAddr = 12'h30A; + 36'h0_0000_1000: CSRAddr = 12'hF14; + 36'h0_0000_2000: CSRAddr = 12'h340; + 36'h0_0000_4000: CSRAddr = 12'h342; + 36'h0_0000_8000: CSRAddr = 12'h343; + 36'h0_0001_0000: CSRAddr = 12'hF11; + 36'h0_0002_0000: CSRAddr = 12'hF12; + 36'h0_0004_0000: CSRAddr = 12'hF13; + 36'h0_0008_0000: CSRAddr = 12'hF15; + 36'h0_0010_0000: CSRAddr = 12'h34A; + 36'h0_0020_0000: CSRAddr = 12'h100; + 36'h0_0040_0000: CSRAddr = 12'h104; + 36'h0_0080_0000: CSRAddr = 12'h105; + 36'h0_0100_0000: CSRAddr = 12'h141; + 36'h0_0200_0000: CSRAddr = 12'h106; + 36'h0_0400_0000: CSRAddr = 12'h10A; + 36'h0_0800_0000: CSRAddr = 12'h180; + 36'h0_1000_0000: CSRAddr = 12'h140; + 36'h0_2000_0000: CSRAddr = 12'h143; + 36'h0_4000_0000: CSRAddr = 12'h142; + 36'h0_8000_0000: CSRAddr = 12'h144; + 36'h1_0000_0000: CSRAddr = 12'h14D; + 36'h2_0000_0000: CSRAddr = 12'h001; + 36'h4_0000_0000: CSRAddr = 12'h002; + 36'h8_0000_0000: CSRAddr = 12'h003; + default : CSRAddr = 12'h000; + endcase + end +endmodule + diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index cf99b9038..97c57415e 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -129,7 +129,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, assign Tag = 32'b0; assign EthType = 16'h005c; - assign RvviAxiWdata = TotalFrameWords[WordCount]; + assign RvviAxiWdata = TotalFrameWords[WordCount[4:0]]; assign RvviAxiWstrb = '1; assign RvviAxiWlast = BurstDone & (CurrState == STATE_TRANS); assign RvviAxiWvalid = (CurrState == STATE_TRANS); diff --git a/src/wally/csrindextoaddr.sv b/src/wally/csrindextoaddr.sv deleted file mode 100644 index 8b2d9e6b7..000000000 --- a/src/wally/csrindextoaddr.sv +++ /dev/null @@ -1,77 +0,0 @@ -/////////////////////////////////////////// -// csrindextoaddr.sv -// -// Written: Rose Thompson ross1728@gmail.com -// Created: 24 January 2024 -// Modified: 24 January 2024 -// -// Purpose: Converts the rvvi CSR index into the CSR address -// -// Documentation: -// -// A component of the CORE-V-WALLY configurable RISC-V project. -// -// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -// -// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -// except in compliance with the License, or, at your option, the Apache License version 2.0. You -// may obtain a copy of the License at -// -// https://solderpad.org/licenses/SHL-2.1/ -// -// Unless required by applicable law or agreed to in writing, any work distributed under the -// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions -// and limitations under the License. -//////////////////////////////////////////////////////////////////////////////////////////////// - -module csrindextoaddr #(parameter TOTAL_CSRS = 36) ( - input logic [TOTAL_CSRS-1:0] CSRWen, - output logic [11:0] CSRAddr); - - always_comb begin - case(CSRWen) - 36'h0_0000_0000: CSRAddr = 13'h000; - 36'h0_0000_0001: CSRAddr = 13'h300; - 36'h0_0000_0002: CSRAddr = 13'h310; - 36'h0_0000_0004: CSRAddr = 13'h305; - 36'h0_0000_0008: CSRAddr = 13'h341; - 36'h0_0000_0010: CSRAddr = 13'h306; - 36'h0_0000_0020: CSRAddr = 13'h320; - 36'h0_0000_0040: CSRAddr = 13'h302; - 36'h0_0000_0080: CSRAddr = 13'h303; - 36'h0_0000_0100: CSRAddr = 13'h344; - 36'h0_0000_0200: CSRAddr = 13'h304; - 36'h0_0000_0400: CSRAddr = 13'h301; - 36'h0_0000_0800: CSRAddr = 13'h30A; - 36'h0_0000_1000: CSRAddr = 13'hF14; - 36'h0_0000_2000: CSRAddr = 13'h340; - 36'h0_0000_4000: CSRAddr = 13'h342; - 36'h0_0000_8000: CSRAddr = 13'h343; - 36'h0_0001_0000: CSRAddr = 13'hF11; - 36'h0_0002_0000: CSRAddr = 13'hF12; - 36'h0_0004_0000: CSRAddr = 13'hF13; - 36'h0_0008_0000: CSRAddr = 13'hF15; - 36'h0_0010_0000: CSRAddr = 13'h34A; - 36'h0_0020_0000: CSRAddr = 13'h100; - 36'h0_0040_0000: CSRAddr = 13'h104; - 36'h0_0080_0000: CSRAddr = 13'h105; - 36'h0_0100_0000: CSRAddr = 13'h141; - 36'h0_0200_0000: CSRAddr = 13'h106; - 36'h0_0400_0000: CSRAddr = 13'h10A; - 36'h0_0800_0000: CSRAddr = 13'h180; - 36'h0_1000_0000: CSRAddr = 13'h140; - 36'h0_2000_0000: CSRAddr = 13'h143; - 36'h0_4000_0000: CSRAddr = 13'h142; - 36'h0_8000_0000: CSRAddr = 13'h144; - 36'h1_0000_0000: CSRAddr = 13'h14D; - 36'h2_0000_0000: CSRAddr = 13'h001; - 36'h4_0000_0000: CSRAddr = 13'h002; - 36'h8_0000_0000: CSRAddr = 13'h003; - default : CSRAddr = 13'h000; - endcase - end -endmodule - From 825dbefcb24f0831c418b0fb5e124e123f5a1f00 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 12:26:03 -0500 Subject: [PATCH 114/163] Fixed bus width error. Have to check this FPGA to make sure this didn't break anything. --- src/rvvi/packetizer.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 97c57415e..54dc9a27f 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -42,7 +42,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, input logic RvviAxiWready ); - localparam TotalFrameLengthBits = 2*48+32+16+187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12); + localparam TotalFrameLengthBits = 2*48+17+16+187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12); localparam TotalFrameLengthBytes = TotalFrameLengthBits / 8; logic [9:0] WordCount; @@ -121,7 +121,7 @@ module packetizer import cvw::*; #(parameter cvw_t P, end assign Length = {4'b0, BytesInFrame}; - assign TotalFrame = {16'b0, rvviDelay, EthType, DstMac, SrcMac}; + assign TotalFrame = {17'b0, rvviDelay, EthType, DstMac, SrcMac}; // *** fix me later assign DstMac = 48'h8F54_0000_1654; // made something up From c463201d6837a2bb33afaabe9c23eb977bd65cc6 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 13:03:21 -0500 Subject: [PATCH 115/163] Moved all rvvi files to rvvi directory. --- src/{wally => rvvi}/regchangedetect.sv | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{wally => rvvi}/regchangedetect.sv (100%) diff --git a/src/wally/regchangedetect.sv b/src/rvvi/regchangedetect.sv similarity index 100% rename from src/wally/regchangedetect.sv rename to src/rvvi/regchangedetect.sv From 1eff86b7ae342557494011a81e69ea909bf90f03 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 13:18:03 -0500 Subject: [PATCH 116/163] Down to 3 verilator warnings in rvvisynth and a 40 warnings in verilog-ethernet. --- src/{wally => rvvi}/priorityaomux.sv | 0 src/rvvi/rvvisynth.sv | 9 ++++++--- 2 files changed, 6 insertions(+), 3 deletions(-) rename src/{wally => rvvi}/priorityaomux.sv (100%) diff --git a/src/wally/priorityaomux.sv b/src/rvvi/priorityaomux.sv similarity index 100% rename from src/wally/priorityaomux.sv rename to src/rvvi/priorityaomux.sv diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index 5ee8b8c52..a98160d47 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -30,7 +30,8 @@ `define FPGA 0 module rvvisynth import cvw::*; #(parameter cvw_t P, - parameter integer MAX_CSRS, TOTAL_CSRS = 36)( + parameter integer MAX_CSRS = 3, + parameter integer TOTAL_CSRS = 36)( input logic clk, reset, input logic StallE, StallM, StallW, FlushE, FlushM, FlushW, // required @@ -64,6 +65,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, logic [TOTAL_CSRS-1:0] CSRWen [MAX_CSRS-1:0]; logic [11:0] CSRAddr [MAX_CSRS-1:0]; logic [MAX_CSRS-1:0] EnabledCSRs; + logic [MAX_CSRS-1:0] CSRCountShort; logic [11:0] CSRCount; logic [177+P.XLEN-1:0] Required; logic [10+2*P.XLEN-1:0] Registers; @@ -94,7 +96,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, // 3. Then use priorityaomux to collect CSR values and addresses for compating into the compressed rvvi format // step 2 - genvar index; + genvar index; for (index = 0; index < TOTAL_CSRS; index = index + 1) begin regchangedetect #(P.XLEN) changedetect(clk, reset, CSRArray[index], CSRArrayWen[index]); end @@ -109,7 +111,8 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRs[(index+1) * (P.XLEN + 12)- 1: index * (P.XLEN + 12)] = {CSRValue[index], CSRAddr[index]}; assign EnabledCSRs[index] = |CSRWenShort; end - assign CSRCount = +EnabledCSRs; + assign CSRCountShort = +EnabledCSRs; + assign CSRCount = {{{12-MAX_CSRS}{1'b0}}, CSRCountShort}; assign rvvi = {CSRs, Registers, Required}; endmodule From bf65cd2817b7a49a1dfb0bf16b2362f253da4fd9 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 14:18:42 -0500 Subject: [PATCH 117/163] Added uart print functions and the Wally banner. SD card can now be initialized. Removed old code from boot.c --- fpga/zsbl/boot.c | 441 ++++------------------------------------------- fpga/zsbl/boot.h | 10 ++ fpga/zsbl/sd.c | 76 ++++++-- fpga/zsbl/sd.h | 10 ++ fpga/zsbl/uart.c | 96 +++++++++++ fpga/zsbl/uart.h | 26 +++ 6 files changed, 239 insertions(+), 420 deletions(-) create mode 100644 fpga/zsbl/uart.c create mode 100644 fpga/zsbl/uart.h diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 6e4780f55..484bddaac 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -2,421 +2,54 @@ #include "boot.h" #include "gpt.h" -/* Card type flags (card_type) */ -#define CT_MMC 0x01 /* MMC ver 3 */ -#define CT_SD1 0x02 /* SD ver 1 */ -#define CT_SD2 0x04 /* SD ver 2 */ -#define CT_SDC (CT_SD1|CT_SD2) /* SD */ -#define CT_BLOCK 0x08 /* Block addressing */ +/* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ -#define CMD0 (0) /* GO_IDLE_STATE */ -#define CMD1 (1) /* SEND_OP_COND */ -#define CMD2 (2) /* SEND_CID */ -#define CMD3 (3) /* RELATIVE_ADDR */ -#define CMD4 (4) -#define CMD5 (5) /* SLEEP_WAKE (SDC) */ -#define CMD6 (6) /* SWITCH_FUNC */ -#define CMD7 (7) /* SELECT */ -#define CMD8 (8) /* SEND_IF_COND */ -#define CMD9 (9) /* SEND_CSD */ -#define CMD10 (10) /* SEND_CID */ -#define CMD11 (11) -#define CMD12 (12) /* STOP_TRANSMISSION */ -#define CMD13 (13) -#define CMD15 (15) -#define CMD16 (16) /* SET_BLOCKLEN */ -#define CMD17 (17) /* READ_SINGLE_BLOCK */ -#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ -#define CMD19 (19) -#define CMD20 (20) -#define CMD23 (23) -#define CMD24 (24) -#define CMD25 (25) -#define CMD27 (27) -#define CMD28 (28) -#define CMD29 (29) -#define CMD30 (30) -#define CMD32 (32) -#define CMD33 (33) -#define CMD38 (38) -#define CMD42 (42) -#define CMD55 (55) /* APP_CMD */ -#define CMD56 (56) -#define ACMD6 (0x80+6) /* define the data bus width */ -#define ACMD41 (0x80+41) /* SEND_OP_COND (ACMD) */ +/* /\* This is not needed. This has everything to do with the FAT */ +/* filesystem stuff that I'm not including. All I need to do is */ +/* initialize the SD card and read from it. Anything in here that is */ +/* checking for potential errors, I'm going to have to temporarily */ +/* do without. */ +/* *\/ */ +/* // if (!count) return RES_PARERR; */ +/* /\* if (drv_status & STA_NOINIT) return RES_NOTRDY; *\/ */ -// Capability bits -#define SDC_CAPABILITY_SD_4BIT 0x0001 -#define SDC_CAPABILITY_SD_RESET 0x0002 -#define SDC_CAPABILITY_ADDR 0xff00 - -// Control bits -#define SDC_CONTROL_SD_4BIT 0x0001 -#define SDC_CONTROL_SD_RESET 0x0002 - -// Card detect bits -#define SDC_CARD_INSERT_INT_EN 0x0001 -#define SDC_CARD_INSERT_INT_REQ 0x0002 -#define SDC_CARD_REMOVE_INT_EN 0x0004 -#define SDC_CARD_REMOVE_INT_REQ 0x0008 - -// Command status bits -#define SDC_CMD_INT_STATUS_CC 0x0001 // Command complete -#define SDC_CMD_INT_STATUS_EI 0x0002 // Any error -#define SDC_CMD_INT_STATUS_CTE 0x0004 // Timeout -#define SDC_CMD_INT_STATUS_CCRC 0x0008 // CRC error -#define SDC_CMD_INT_STATUS_CIE 0x0010 // Command code check error - -// Data status bits -#define SDC_DAT_INT_STATUS_TRS 0x0001 // Transfer complete -#define SDC_DAT_INT_STATUS_ERR 0x0002 // Any error -#define SDC_DAT_INT_STATUS_CTE 0x0004 // Timeout -#define SDC_DAT_INT_STATUS_CRC 0x0008 // CRC error -#define SDC_DAT_INT_STATUS_CFE 0x0010 // Data FIFO underrun or overrun - - -#define ERR_EOF 30 -#define ERR_NOT_ELF 31 -#define ERR_ELF_BITS 32 -#define ERR_ELF_ENDIANNESS 33 -#define ERR_CMD_CRC 34 -#define ERR_CMD_CHECK 35 -#define ERR_DATA_CRC 36 -#define ERR_DATA_FIFO 37 -#define ERR_BUF_ALIGNMENT 38 -#define FR_DISK_ERR 39 -#define FR_TIMEOUT 40 - -struct sdc_regs { - volatile uint32_t argument; - volatile uint32_t command; - volatile uint32_t response1; - volatile uint32_t response2; - volatile uint32_t response3; - volatile uint32_t response4; - volatile uint32_t data_timeout; - volatile uint32_t control; - volatile uint32_t cmd_timeout; - volatile uint32_t clock_divider; - volatile uint32_t software_reset; - volatile uint32_t power_control; - volatile uint32_t capability; - volatile uint32_t cmd_int_status; - volatile uint32_t cmd_int_enable; - volatile uint32_t dat_int_status; - volatile uint32_t dat_int_enable; - volatile uint32_t block_size; - volatile uint32_t block_count; - volatile uint32_t card_detect; - volatile uint32_t res_50; - volatile uint32_t res_54; - volatile uint32_t res_58; - volatile uint32_t res_5c; - volatile uint64_t dma_addres; -}; - -#define MAX_BLOCK_CNT 0x1000 - -#define SDC 0x00013000; - -// static struct sdc_regs * const regs __attribute__((section(".rodata"))) = (struct sdc_regs *)0x00013000; - -// static int errno __attribute__((section(".bss"))); -// static DSTATUS drv_status __attribute__((section(".bss"))); -// static BYTE card_type __attribute__((section(".bss"))); -// static uint32_t response[4] __attribute__((section(".bss"))); -// static int alt_mem __attribute__((section(".bss"))); - -/*static const char * errno_to_str(void) { - switch (errno) { - case ERR_EOF: return "Unexpected EOF"; - case ERR_NOT_ELF: return "Not an ELF file"; - case ERR_ELF_BITS: return "Wrong ELF word size"; - case ERR_ELF_ENDIANNESS: return "Wrong ELF endianness"; - case ERR_CMD_CRC: return "Command CRC error"; - case ERR_CMD_CHECK: return "Command code check error"; - case ERR_DATA_CRC: return "Data CRC error"; - case ERR_DATA_FIFO: return "Data FIFO error"; - case ERR_BUF_ALIGNMENT: return "Bad buffer alignment"; - case FR_DISK_ERR: return "Disk error"; - case FR_TIMEOUT: return "Timeout"; - } - return "Unknown error code"; - }*/ - -static void usleep(unsigned us) { - uintptr_t cycles0; - uintptr_t cycles1; - asm volatile ("csrr %0, 0xB00" : "=r" (cycles0)); - for (;;) { - asm volatile ("csrr %0, 0xB00" : "=r" (cycles1)); - if (cycles1 - cycles0 >= us * 100) break; - } -} - -static int sdc_cmd_finish(unsigned cmd, uint32_t * response) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; +/* uint32_t response[4]; */ +/* struct sdc_regs * regs = (struct sdc_regs *)SDC; */ - while (1) { - unsigned status = regs->cmd_int_status; - if (status) { - // clear interrupts - regs->cmd_int_status = 0; - while (regs->software_reset != 0) {} - if (status == SDC_CMD_INT_STATUS_CC) { - // get response - response[0] = regs->response1; - response[1] = regs->response2; - response[2] = regs->response3; - response[3] = regs->response4; - return 0; - } - /* errno = FR_DISK_ERR; - if (status & SDC_CMD_INT_STATUS_CTE) errno = FR_TIMEOUT; - if (status & SDC_CMD_INT_STATUS_CCRC) errno = ERR_CMD_CRC; - if (status & SDC_CMD_INT_STATUS_CIE) errno = ERR_CMD_CHECK;*/ - break; - } - } - return -1; -} +/* /\* Convert LBA to byte address if needed *\/ */ +/* if (!(card_type & CT_BLOCK)) sector *= 512; */ +/* while (count > 0) { */ +/* UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; */ +/* unsigned bytes = bcnt * 512; */ +/* if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; */ +/* if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; */ +/* sector += (card_type & CT_BLOCK) ? bcnt : bytes; */ +/* count -= bcnt; */ +/* buf += bytes; */ +/* } */ -static int sdc_data_finish(void) { - int status; - struct sdc_regs * regs = (struct sdc_regs *)SDC; - - while ((status = regs->dat_int_status) == 0) {} - regs->dat_int_status = 0; - while (regs->software_reset != 0) {} +/* return 0;; */ +/* } */ - if (status == SDC_DAT_INT_STATUS_TRS) return 0; - /* errno = FR_DISK_ERR; - if (status & SDC_DAT_INT_STATUS_CTE) errno = FR_TIMEOUT; - if (status & SDC_DAT_INT_STATUS_CRC) errno = ERR_DATA_CRC; - if (status & SDC_DAT_INT_STATUS_CFE) errno = ERR_DATA_FIFO;*/ - return -1; -} - -static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; +int disk_read(BYTE * buf, LBA_t sector, UINT count) { - unsigned command = (cmd & 0x3f) << 8; - switch (cmd) { - case CMD0: - case CMD4: - case CMD15: - // No responce - break; - case CMD11: - case CMD13: - case CMD16: - case CMD17: - case CMD18: - case CMD19: - case CMD23: - case CMD24: - case CMD25: - case CMD27: - case CMD30: - case CMD32: - case CMD33: - case CMD42: - case CMD55: - case CMD56: - case ACMD6: - // R1 - command |= 1; // 48 bits - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD7: - case CMD12: - case CMD20: - case CMD28: - case CMD29: - case CMD38: - // R1b - command |= 1; // 48 bits - command |= 1 << 2; // busy - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD2: - case CMD9: - case CMD10: - // R2 - command |= 2; // 136 bits - command |= 1 << 3; // resp CRC - break; - case ACMD41: - // R3 - command |= 1; // 48 bits - break; - case CMD3: - // R6 - command |= 1; // 48 bits - command |= 1 << 2; // busy - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD8: - // R7 - command |= 1; // 48 bits - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - } - - if (blocks) { - command |= 1 << 5; - if ((intptr_t)buf & 3) { - // errno = ERR_BUF_ALIGNMENT; - return -1; - } - regs->dma_addres = (uint64_t)(intptr_t)buf; - regs->block_size = 511; - regs->block_count = blocks - 1; - regs->data_timeout = 0x1FFFFFF; - } - - regs->command = command; - regs->cmd_timeout = 0xFFFFF; - regs->argument = arg; - - if (sdc_cmd_finish(cmd, response) < 0) return -1; - if (blocks) return sdc_data_finish(); - - return 0; -} - -#define send_cmd(cmd, arg, response) send_data_cmd(cmd, arg, NULL, 0, response) - -static BYTE ini_sd(void) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; - unsigned rca; - BYTE card_type; - uint32_t response[4]; - - /* Reset controller */ - regs->software_reset = 1; - while ((regs->software_reset & 1) == 0) {} - - // This clock divider is meant to initialize the card at - // 400kHz - - // 22MHz/400kHz = 55 (base 10) = 0x37 - 0x01 = 0x36 - regs->clock_divider = 0x36; - regs->software_reset = 0; - while (regs->software_reset) {} - usleep(5000); - - card_type = 0; - // drv_status = STA_NOINIT; - - if (regs->capability & SDC_CAPABILITY_SD_RESET) { - /* Power cycle SD card */ - regs->control |= SDC_CONTROL_SD_RESET; - usleep(1000000); - regs->control &= ~SDC_CONTROL_SD_RESET; - usleep(100000); - } - - /* Enter Idle state */ - send_cmd(CMD0, 0, response); - - card_type = CT_SD1; - if (send_cmd(CMD8, 0x1AA, response) == 0) { - if ((response[0] & 0xfff) != 0x1AA) { - // errno = ERR_CMD_CHECK; - return -1; - } - card_type = CT_SD2; - } - - /* Wait for leaving idle state (ACMD41 with HCS bit) */ - while (1) { - /* ACMD41, Set Operating Conditions: Host High Capacity & 3.3V */ - if (send_cmd(CMD55, 0, response) < 0 || send_cmd(ACMD41, 0x40300000, response) < 0) return -1; - if (response[0] & (1 << 31)) { - if (response[0] & (1 << 30)) card_type |= CT_BLOCK; - break; - } - } - - /* Enter Identification state */ - if (send_cmd(CMD2, 0, response) < 0) return -1; - - /* Get RCA (Relative Card Address) */ - rca = 0x1234; - if (send_cmd(CMD3, rca << 16, response) < 0) return -1; - rca = response[0] >> 16; - - /* Select card */ - if (send_cmd(CMD7, rca << 16, response) < 0) return -1; - - /* Clock 25MHz */ - // 22Mhz/2 = 11Mhz - regs->clock_divider = 1; - usleep(10000); - - /* Bus width 1-bit */ - regs->control = 0; - if (send_cmd(CMD55, rca << 16, response) < 0 || send_cmd(ACMD6, 0, response) < 0) return -1; - - /* Set R/W block length to 512 */ - if (send_cmd(CMD16, 512, response) < 0) return -1; - - // drv_status &= ~STA_NOINIT; - return card_type; -} - -int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { - - /* This is not needed. This has everything to do with the FAT - filesystem stuff that I'm not including. All I need to do is - initialize the SD card and read from it. Anything in here that is - checking for potential errors, I'm going to have to temporarily - do without. - */ - // if (!count) return RES_PARERR; - /* if (drv_status & STA_NOINIT) return RES_NOTRDY; */ - - uint32_t response[4]; - struct sdc_regs * regs = (struct sdc_regs *)SDC; - - /* Convert LBA to byte address if needed */ - if (!(card_type & CT_BLOCK)) sector *= 512; - while (count > 0) { - UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; - unsigned bytes = bcnt * 512; - if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; - if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; - sector += (card_type & CT_BLOCK) ? bcnt : bytes; - count -= bcnt; - buf += bytes; - } - - return 0;; } +// copyFlash: -------------------------------------------------------- +// A lot happens in this function: +// * The Wally banner is printed +// * The peripherals are initialized void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { - BYTE card_type; int ret = 0; - - card_type = ini_sd(); - // BYTE * buf = (BYTE *)Dst; - - // if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/; + // Initialize UART for messages + init_uart(); + + // Print the wally banner + print_uart(BANNER); + + + init_sd(); ret = gpt_load_partitions(card_type); } - -/* -int main() { - ini_sd(); - - - return 0; -} -*/ diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 77d403145..cb0f4e7f3 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -19,6 +19,16 @@ typedef QWORD LBA_t; #define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START #define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR +#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\n" \ +" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\n" \ +" █▄█ █▄█ █ █ █▄▄ ▀▄▀\n" \ +" ____ ____ ____ ___ ___ ____ ___\n" \ +" \\ \\ / / / \\ | | | | \\ \\ / /\n" \ +" \\ \\ __ / / / \\ | | | | \\ \\/ /\n" \ +" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\n" \ +" \\ / / ____ \\ | |___ | |___ | |\n" \ +" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" + // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type); diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index aacea0db9..4669aeb0b 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,5 +1,6 @@ #include "sd.h" #include "spi.h" +#include "uart.h" // Parallel byte update CRC7-CCITT algorithm. // The result is the CRC7 result, left shifted over by 1 @@ -23,27 +24,44 @@ uint16_t crc16(uint16_t crc, uint8_t data) { return crc; } +// sd_cmd ------------------------------------------------------------ +// Sends SD card command using SPI mode. +// This function: +// * Chooses the response length based on the input command +// * Makes use of SPI's full duplex. For every byte sent, +// a byte is received. Thus for every byte sent as part of +// a command, a useless byte must be read from the receive +// FIFO. +// * Takes advantage of the Sifive SPI peripheral spec's +// watermark and interrupt features to determine when a +// transfer is complete. This should save on cycles since +// no arbitrary delays need to be added. uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t response_len; uint8_t i; uint64_t r; uint8_t rbyte; - + + // Initialize the response with 0's. + r = 0; + + // Choose response length based on cmd input. + // Most commands return an R1 format response. switch (cmd) { - case 0: - response_len = 1; - break; case 8: - response_len = 7 + response_len = R7_RESPONSE; break; + case 12: + response_len = R1B_RESPONSE; default: - response_len = 1; + response_len = R1_RESPONSE; break; } // Make interrupt pending after response fifo receives the correct - // response length. - write_reg(SPI_RXMARK, response_len); + // response length. Probably unecessary so let's wait and see what + // happens. + // write_reg(SPI_RXMARK, response_len); // Write all 6 bytes into transfer fifo spi_sendbyte(0x40 | cmd); @@ -79,18 +97,44 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { } return r; -} +} // sd_cmd -#define cmd0() sd_cmd( 0, 0x00000000, 0x95) -#define cmd8() sd_cmd( 8, 0x000001aa, 0x87) -// CMD55 has to be sent before ACMD41 (it means the next command is -// application specific) -#define cmd55() sd_cmd(55, 0x00000000, 0x65) -#defube acmd41() sd_cmd(41, 0x40000000, 0x77) +// Utility defines for CMD0, CMD8, CMD55, and ACMD41 +#define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state +#define CMD8() sd_cmd( 8, 0x000001aa, 0x87) // +#define CMD55() sd_cmd(55, 0x00000000, 0x65) // +#define ACMD41() sd_cmd(41, 0x40000000, 0x77) // +// init_sd: ---------------------------------------------------------- +// This first initializes the SPI peripheral then initializes the SD +// card itself. We use the uart to display anything that goes wrong. void init_sd(){ init_spi(); - cmd0() + uint64_t r; + + print_uart("Initializing SD Card in SPI mode"); + + // Reset SD Card command + // Initializes SD card into SPI mode if CS is asserted '0' + if (!(( r = CMD0() ) & 0x10) ) { + print_uart("SD ERROR: "); + print_uart_byte(r & 0xff); + print_uart("\r\n"); + } + + // + if (!(( r = CMD8() ) & 0x10 )) { + print_uart("SD ERROR: "); + print_uart_byte(r & 0xff); + print_uart("\r\n"); + } + + do { + CMD55(); + r = ACMD41(); + } while (r == 0x1); + + print_uart("SD card is initialized"); } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index f08941364..a70d203e7 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -2,6 +2,16 @@ #include <stdint.h> +// Command names +#define SD_CMD_STOP_TRANSMISSION 12 +#define SD_CMD_READ_BLOCK_MULTIPLE 18 +#define SD_DATA_TOKEN 0xfe + +// Response lengths in bytes +#define R1_RESPONSE 1 +#define R7_RESPONSE 7 +#define R1B_RESPONSE 2 + uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c new file mode 100644 index 000000000..a08690069 --- /dev/null +++ b/fpga/zsbl/uart.c @@ -0,0 +1,96 @@ +#include "uart.h" + + +void write_reg_u8(uintptr_t addr, uint8_t value) +{ + volatile uint8_t *loc_addr = (volatile uint8_t *)addr; + *loc_addr = value; +} + +uint8_t read_reg_u8(uintptr_t addr) +{ + return *(volatile uint8_t *)addr; +} + +int is_transmit_empty() +{ + return read_reg_u8(UART_LINE_STATUS) & 0x20; +} + +int is_receive_empty() +{ + return !(read_reg_u8(UART_LINE_STATUS) & 0x1); +} + +void write_serial(char a) +{ + while (is_transmit_empty() == 0) {}; + + write_reg_u8(UART_THR, a); +} + +void init_uart(uint32_t freq, uint32_t baud) +{ + uint32_t divisor = freq / (baud << 4); + + write_reg_u8(UART_IER, 0x00); // Disable all interrupts + write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) + write_reg_u8(UART_DLL, divisor); // divisor (lo byte) + write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) + write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit + write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold +} + +void print_uart(const char *str) +{ + const char *cur = &str[0]; + while (*cur != '\0') + { + write_serial((uint8_t)*cur); + ++cur; + } +} + +uint8_t bin_to_hex_table[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + +void bin_to_hex(uint8_t inp, uint8_t res[2]) +{ + res[1] = bin_to_hex_table[inp & 0xf]; + res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; + return; +} + +void print_uart_int(uint32_t addr) +{ + int i; + for (i = 3; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_addr(uint64_t addr) +{ + int i; + for (i = 7; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_byte(uint8_t byte) +{ + uint8_t hex[2]; + bin_to_hex(byte, hex); + write_serial(hex[0]); + write_serial(hex[1]); +} diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h new file mode 100644 index 000000000..18710e76b --- /dev/null +++ b/fpga/zsbl/uart.h @@ -0,0 +1,26 @@ +#pragma once +#include <stdint.h> + +#define UART_BASE 0x10000000 + +#define UART_RBR UART_BASE + 0x00 +#define UART_THR UART_BASE + 0x00 +#define UART_IER UART_BASE + 0x01 +#define UART_IIR UART_BASE + 0x02 +#define UART_FCR UART_BASE + 0x02 +#define UART_LCR UART_BASE + 0x03 +#define UART_MCR UART_BASE + 0x04 +#define UART_LSR UART_BASE + 0x05 +#define UART_MSR UART_BASE + 0x06 +#define UART_SCR UART_BASE + 0x07 +#define UART_DLL UART_BASE + 0x00 +#define UART_DLM UART_BASE + 0x01 + +void init_uart(); +void write_reg_u8(uintptr_t addr, uint8_t value); +uint8_t read_reg_u8(uintptr_t addr); +int read_serial(uint8_t *res); +void print_uart(const char* str); +void print_uart_int(uint32_t addr); +void print_uart_addr(uint64_t addr); +void print_uart_byte(uint8_t byte); From 9ccb0eb027679351e81d9cf41d0cfd494fe05e24 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 15:46:18 -0500 Subject: [PATCH 118/163] Removed references to card_type. --- fpga/zsbl/gpt.c | 12 ++++++------ fpga/zsbl/gpt.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 97e3e4e46..65f56924b 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -10,7 +10,7 @@ */ -int gpt_load_partitions(BYTE card_type) { +int gpt_load_partitions() { // In this version of the GPT partition code // I'm going to assume that the SD card is already initialized. @@ -21,7 +21,7 @@ int gpt_load_partitions(BYTE card_type) { int ret = 0; //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */); - ret = disk_read(lba1_buf, 1, 1, card_type); + ret = disk_read(lba1_buf, 1, 1); /* Possible error handling with UART message if ( ret != 0 ) { @@ -31,16 +31,16 @@ int gpt_load_partitions(BYTE card_type) { gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; BYTE lba2_buf[512]; - ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1, card_type); + ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1); // Load parition entries for the relevant boot partitions. partition_entries_t *fdt = (partition_entries_t *)(lba2_buf); partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128); partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); - ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1, card_type); - ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1, card_type); - ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1, card_type); + ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); + ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); + ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); return 0; } diff --git a/fpga/zsbl/gpt.h b/fpga/zsbl/gpt.h index 4aefae229..5ce5e1d4b 100644 --- a/fpga/zsbl/gpt.h +++ b/fpga/zsbl/gpt.h @@ -37,4 +37,4 @@ typedef struct partition_entries } partition_entries_t; // Find boot partition and load it to the destination -int gpt_load_partitions(BYTE card_type); +int gpt_load_partitions(); From 57eeba5c8ca7efa6f202ab915259b2c8ddb7720e Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 15:47:23 -0500 Subject: [PATCH 119/163] Progress made on implementing new disk read function. --- fpga/zsbl/boot.c | 25 ++++++++++++++++++++++++- fpga/zsbl/sd.c | 1 + fpga/zsbl/spi.c | 18 ++++++++++++++++++ fpga/zsbl/spi.h | 2 +- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 484bddaac..16f7c0430 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -1,6 +1,9 @@ #include <stddef.h> #include "boot.h" #include "gpt.h" +#include "uart.h" +#include "spi.h" +#include "sd.h" /* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ @@ -32,7 +35,27 @@ /* } */ int disk_read(BYTE * buf, LBA_t sector, UINT count) { + uint64_t r; + UINT i; + uint8_t crc = 0; + crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE); + crc = crc7(crc, (sector >> 24) & 0xff); + crc = crc7(crc, (sector >> 16) & 0xff); + crc = crc7(crc, (sector >> 8) & 0xff); + crc = crc7(crc, sector & 0xff); + crc = crc | 1; + + if (sd_cmd(18, sector &, crc) != 0x00) { + print_uart("disk_read: CMD18 failed. r = "); + print_byte(r & 0xff); + return -1; + } + + // Begin reading + for (i = 0; i < count; i++) { + + } } // copyFlash: -------------------------------------------------------- @@ -48,7 +71,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Print the wally banner print_uart(BANNER); - + // Intialize the SD card init_sd(); ret = gpt_load_partitions(card_type); diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 4669aeb0b..c2a6eed54 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -99,6 +99,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { return r; } // sd_cmd + // Utility defines for CMD0, CMD8, CMD55, and ACMD41 #define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state #define CMD8() sd_cmd( 8, 0x000001aa, 0x87) // diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index c812327f4..687a98ceb 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -58,6 +58,24 @@ inline void waitrx() { while(read_reg(SPI_IP) & 2)) {} } +uint64_t spi_read64() { + uint64_t r; + uint8_t rbyte; + int i; + + for (i = 0; i < 8; i++) { + spi_sendbyte(0xFF); + } + + waittx(); + + for (i = 0; i < 8; i++) { + rbyte = spi_readbyte(); + r = r | (rbyte << ((8 - 1 - i)*8)); + } + + return r; +} // Initialize Sifive FU540 based SPI Controller void spi_init() { diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index a035f0ab5..e91bcc0ea 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -55,7 +55,7 @@ inline void waittx(); inline void waitrx(); uint8_t spi_txrx(uint8_t byte); inline uint8_t spi_readbyte(); - +uint64_t spi_read64(); void spi_init(); #endif From 54e02896088bb6303830e2330a2775c75a33d99c Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 16:16:11 -0500 Subject: [PATCH 120/163] Fixed bugs in the rvvi synth logic which encoded csr instructions. --- src/rvvi/rvvisynth.sv | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index a98160d47..d4847c9d4 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -102,14 +102,26 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, end // step 3a - for(index = 0; index < MAX_CSRS; index = index + 1) begin + logic [TOTAL_CSRS-1:0] CSRWenPriorityMatrix [MAX_CSRS-1:0]; + logic [TOTAL_CSRS-1:0] CSRWenFilterMatrix [MAX_CSRS-1:0]; + + priorityaomux #(TOTAL_CSRS, P.XLEN) firstpriorityaomux(CSRArrayWen, CSRArray, CSRValue[0], CSRWenPriorityMatrix[0]); + assign CSRWenFilterMatrix[0] = CSRArrayWen; + + for(index = 1; index < MAX_CSRS; index = index + 1) begin +/* -----\/----- EXCLUDED -----\/----- logic [MAX_CSRS-index-1:0] CSRWenShort; priorityaomux #(MAX_CSRS-index, P.XLEN) priorityaomux(CSRArrayWen[MAX_CSRS-1:index], CSRArray[MAX_CSRS-1:index], CSRValue[index], CSRWenShort); assign CSRWen[index] = {{{index}{1'b0}}, CSRWenShort}; + -----/\----- EXCLUDED -----/\----- */ + priorityaomux #(TOTAL_CSRS, P.XLEN) priorityaomux(CSRWenFilterMatrix[index], CSRArray, CSRValue[index], CSRWenPriorityMatrix[index]); + assign CSRWenFilterMatrix[index] = CSRWenFilterMatrix[index-1] & ~CSRWenPriorityMatrix[index-1]; + end + for(index = 0; index < MAX_CSRS; index = index + 1) begin // step 3b - csrindextoaddr #(TOTAL_CSRS) csrindextoaddr(CSRWen[index], CSRAddr[index]); + csrindextoaddr #(TOTAL_CSRS) csrindextoaddr(CSRWenPriorityMatrix[index], CSRAddr[index]); assign CSRs[(index+1) * (P.XLEN + 12)- 1: index * (P.XLEN + 12)] = {CSRValue[index], CSRAddr[index]}; - assign EnabledCSRs[index] = |CSRWenShort; + assign EnabledCSRs[index] = |CSRWenPriorityMatrix[index]; end assign CSRCountShort = +EnabledCSRs; assign CSRCount = {{{12-MAX_CSRS}{1'b0}}, CSRCountShort}; From 57ea39d6857b5227c19bb46f51a0d64fead0ea9f Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 16:22:23 -0500 Subject: [PATCH 121/163] Fixed rvvi csr counting. --- src/rvvi/rvvisynth.sv | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index d4847c9d4..7bdc05d10 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -123,7 +123,15 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRs[(index+1) * (P.XLEN + 12)- 1: index * (P.XLEN + 12)] = {CSRValue[index], CSRAddr[index]}; assign EnabledCSRs[index] = |CSRWenPriorityMatrix[index]; end - assign CSRCountShort = +EnabledCSRs; + + integer index2; + always_comb begin + CSRCountShort = '0; + for(index2 = 0; index2 < MAX_CSRS; index2++) begin + CSRCountShort += EnabledCSRs[index2]; + end + end + assign CSRCount = {{{12-MAX_CSRS}{1'b0}}, CSRCountShort}; assign rvvi = {CSRs, Registers, Required}; From ab00ea5a5cffd862d855e067d57fb4ab3928bb68 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 16:32:29 -0500 Subject: [PATCH 122/163] Added sd_read64 to help with block reads and crc checking. --- fpga/zsbl/sd.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index c2a6eed54..87e78e7fe 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -99,6 +99,25 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { return r; } // sd_cmd +uint64_t sd_read64(uint16_t * crc) { + uint64_t r; + uint8_t rbyte; + int i; + + for (i = 0; i < 8; i++) { + spi_sendbyte(0xFF); + } + + waittx(); + + for (i = 0; i < 8; i++) { + rbyte = spi_readbyte(); + *crc = crc16(*crc, rbyte); + r = r | (rbyte << ((8 - 1 - i)*8)); + } + + return r; +} // Utility defines for CMD0, CMD8, CMD55, and ACMD41 #define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state From a8b9e7776b4d2fd029f0a2b6f75566ce45d2d81d Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 16:32:52 -0500 Subject: [PATCH 123/163] Added some minor error checking to gpt.c. --- fpga/zsbl/gpt.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 65f56924b..90948935b 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -38,9 +38,26 @@ int gpt_load_partitions() { partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128); partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); + // Load device tree ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); + if (ret < 0) { + print_uart("Failed to load device tree!"); + return -1; + } + + // Load OpenSBI ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); + if (ret < 0) { + print_uart("Failed to load OpenSBI!"); + return -1; + } + + // Load Linux ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); + if (ret < 0) { + print_uart("Failed to load Linux!"); + return -1; + } return 0; } From 5f0addd69a25a0b1384ea6cd64f0419058f8f311 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 16:33:49 -0500 Subject: [PATCH 124/163] Initial pass on SPI based bootloader code finished. --- fpga/zsbl/boot.c | 32 +++++++++++++++++++++++++++++++- fpga/zsbl/sd.h | 1 + fpga/zsbl/spi.c | 6 ++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 16f7c0430..96bde4205 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -52,10 +52,40 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { return -1; } - // Begin reading + // Begin reading blocks for (i = 0; i < count; i++) { + uint16_t crc, crc_exp; + + // Read the data token + r = spi_readbyte(); + if (r != SD_DATA_TOKEN) { + print_uart("Didn't receive data token first thing. Shoot: "); + print_byte(r & 0xff); + return -1; + } + + // Read block into memory. + for (int j = 0; j < 8; j++) { + *buf = sd_read64(&crc); + buf = buf + 64; + } + + // Read CRC16 and check + crc_exp = ((uint16_t)spi_txrx(0xff) << 8); + crc_exp |= spi_txrx(0xff); + + if (crc != crc_exp) { + print_uart("Stinking CRC16 didn't match on block "); + print_int(i); + print_uart("\r\n"); + return -1; + } } + + sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01); + spi_txrx(0xff); + return 0; } // copyFlash: -------------------------------------------------------- diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index a70d203e7..37e4a2c94 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -15,4 +15,5 @@ uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); +uint64_t sd_read64(uint16_t * crc); void init_sd(); diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 687a98ceb..76985a350 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -58,6 +58,12 @@ inline void waitrx() { while(read_reg(SPI_IP) & 2)) {} } +uint8_t spi_txrx(uint8_t byte) { + spi_sendbyte(0xFF); + waittx(); + return spi_readbyte(); +} + uint64_t spi_read64() { uint64_t r; uint8_t rbyte; From e8e71ad643370f6401e6253cb31b1fdd639b57b4 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 16:35:05 -0500 Subject: [PATCH 125/163] Code cleanup. --- src/rvvi/rvvisynth.sv | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index 7bdc05d10..83c865529 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -27,8 +27,6 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -`define FPGA 0 - module rvvisynth import cvw::*; #(parameter cvw_t P, parameter integer MAX_CSRS = 3, parameter integer TOTAL_CSRS = 36)( @@ -109,11 +107,6 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, assign CSRWenFilterMatrix[0] = CSRArrayWen; for(index = 1; index < MAX_CSRS; index = index + 1) begin -/* -----\/----- EXCLUDED -----\/----- - logic [MAX_CSRS-index-1:0] CSRWenShort; - priorityaomux #(MAX_CSRS-index, P.XLEN) priorityaomux(CSRArrayWen[MAX_CSRS-1:index], CSRArray[MAX_CSRS-1:index], CSRValue[index], CSRWenShort); - assign CSRWen[index] = {{{index}{1'b0}}, CSRWenShort}; - -----/\----- EXCLUDED -----/\----- */ priorityaomux #(TOTAL_CSRS, P.XLEN) priorityaomux(CSRWenFilterMatrix[index], CSRArray, CSRValue[index], CSRWenPriorityMatrix[index]); assign CSRWenFilterMatrix[index] = CSRWenFilterMatrix[index-1] & ~CSRWenPriorityMatrix[index-1]; end From dcb2edf8888175f078d10b80c491a7df264bafac Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 17:00:32 -0500 Subject: [PATCH 126/163] Fixed syntax bugs. inline functions are now static and in the spi.h header. --- fpga/zsbl/boot.c | 10 +++++----- fpga/zsbl/boot.h | 2 +- fpga/zsbl/sd.c | 2 +- fpga/zsbl/spi.c | 46 +++++++++++++++++++++++----------------------- fpga/zsbl/spi.h | 48 ++++++++++++++++++++++++++++++++++++++---------- fpga/zsbl/uart.c | 4 ++-- 6 files changed, 70 insertions(+), 42 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 96bde4205..786879c49 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -46,9 +46,9 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { crc = crc7(crc, sector & 0xff); crc = crc | 1; - if (sd_cmd(18, sector &, crc) != 0x00) { + if (sd_cmd(18, sector & 0xffffffff, crc) != 0x00) { print_uart("disk_read: CMD18 failed. r = "); - print_byte(r & 0xff); + print_uart_byte(r & 0xff); return -1; } @@ -60,7 +60,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { r = spi_readbyte(); if (r != SD_DATA_TOKEN) { print_uart("Didn't receive data token first thing. Shoot: "); - print_byte(r & 0xff); + print_uart_byte(r & 0xff); return -1; } @@ -76,7 +76,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { if (crc != crc_exp) { print_uart("Stinking CRC16 didn't match on block "); - print_int(i); + print_uart_int(i); print_uart("\r\n"); return -1; } @@ -104,5 +104,5 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Intialize the SD card init_sd(); - ret = gpt_load_partitions(card_type); + ret = gpt_load_partitions(); } diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index cb0f4e7f3..2048ca47c 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -30,7 +30,7 @@ typedef QWORD LBA_t; " \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" // Export disk_read -int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type); +int disk_read(BYTE * buf, LBA_t sector, UINT count); #endif // WALLYBOOT diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 87e78e7fe..585b98281 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -129,7 +129,7 @@ uint64_t sd_read64(uint16_t * crc) { // This first initializes the SPI peripheral then initializes the SD // card itself. We use the uart to display anything that goes wrong. void init_sd(){ - init_spi(); + spi_init(); uint64_t r; diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 76985a350..cbb9fa2eb 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -30,33 +30,29 @@ #include "spi.h" // Write to a register -inline void write_reg(uintptr_t addr, uint32_t value) { - volatile uint32_t * loc = (volatile uint32_t *) addr; - *loc = value; -} +/* inline void write_reg(uintptr_t addr, uint32_t value) { */ +/* volatile uint32_t * loc = (volatile uint32_t *) addr; */ +/* *loc = value; */ +/* } */ -// Read a register -inline void read_reg(uintptr_t addr) { - return *(volatile uint32_t *) addr; -} +/* // Read a register */ +/* inline uint32_t read_reg(uintptr_t addr) { */ +/* return *(volatile uint32_t *) addr; */ +/* } */ -// Queues a single byte in the transfer fifo -inline void spi_sendbyte(uint8_t byte) { - // Write byte to transfer fifo - write_reg(SPI_TXDATA, byte); -} +/* // Queues a single byte in the transfer fifo */ +/* inline void spi_sendbyte(uint8_t byte) { */ +/* // Write byte to transfer fifo */ +/* write_reg(SPI_TXDATA, byte); */ +/* } */ -inline uint8_t spi_readbyte() { - return read_reg(SPI_RXDATA); -} +/* inline void waittx() { */ +/* while(!(read_reg(SPI_IP) & 1)) {} */ +/* } */ -inline void waittx() { - while(!(read_reg(SPI_IP) & 1)) {} -} - -inline void waitrx() { - while(read_reg(SPI_IP) & 2)) {} -} +/* inline void waitrx() { */ +/* while(read_reg(SPI_IP) & 2) {} */ +/* } */ uint8_t spi_txrx(uint8_t byte) { spi_sendbyte(0xFF); @@ -64,6 +60,10 @@ uint8_t spi_txrx(uint8_t byte) { return spi_readbyte(); } +/* inline uint8_t spi_readbyte() { */ +/* return read_reg(SPI_RXDATA); */ +/* } */ + uint64_t spi_read64() { uint64_t r; uint8_t rbyte; diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index e91bcc0ea..bc85c768f 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -28,15 +28,15 @@ #define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */ /* delay0 bits */ -#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((uint32_t)(x)) #define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU -#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((uint32_t)(x) << 16) #define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) /* delay1 bits */ -#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((uint32_t)(x)) #define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU -#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((uint32_t)(x) << 16) #define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) /* csmode bits */ @@ -48,14 +48,42 @@ #define WAITTX while(!(read_reg(SPI_IP) & 1) {} #define WAITRX while(read_reg(SPI_IP) & 2) {} -inline void write_reg(uintptr_t addr, uint32_t value); -inline uint32_t read_reg(uintptr_t addr); -inline void spi_sendbyte(uint8_t byte); -inline void waittx(); -inline void waitrx(); +// inline void write_reg(uintptr_t addr, uint32_t value); +//inline uint32_t read_reg(uintptr_t addr); +//inline void spi_sendbyte(uint8_t byte); +//inline void waittx(); +//inline void waitrx(); uint8_t spi_txrx(uint8_t byte); -inline uint8_t spi_readbyte(); +//inline uint8_t spi_readbyte(); uint64_t spi_read64(); void spi_init(); +static inline void write_reg(uintptr_t addr, uint32_t value) { + volatile uint32_t * loc = (volatile uint32_t *) addr; + *loc = value; +} + +// Read a register +static inline uint32_t read_reg(uintptr_t addr) { + return *(volatile uint32_t *) addr; +} + +// Queues a single byte in the transfer fifo +static inline void spi_sendbyte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); +} + +static inline void waittx() { + while(!(read_reg(SPI_IP) & 1)) {} +} + +static inline void waitrx() { + while(read_reg(SPI_IP) & 2) {} +} + +static inline uint8_t spi_readbyte() { + return read_reg(SPI_RXDATA); +} + #endif diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index a08690069..be3270e28 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -14,12 +14,12 @@ uint8_t read_reg_u8(uintptr_t addr) int is_transmit_empty() { - return read_reg_u8(UART_LINE_STATUS) & 0x20; + return read_reg_u8(UART_LSR) & 0x20; } int is_receive_empty() { - return !(read_reg_u8(UART_LINE_STATUS) & 0x1); + return !(read_reg_u8(UART_LSR) & 0x1); } void write_serial(char a) From f1cc7dd5a378111c05f84f80601bd79fe5589442 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 23 Jul 2024 17:26:39 -0500 Subject: [PATCH 127/163] Fixed verilog bugs. --- fpga/src/fpgaTopArtyA7.sv | 3 +-- src/uncore/uncore.sv | 4 ++-- src/wally/wallypipelinedsoc.sv | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 6a2f055ba..31848f33e 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -80,7 +80,6 @@ module fpgaTop wire [63:0] HRDATAEXT; wire HREADYEXT; wire HRESPEXT; - wire HSELEXTSDC; // TEMP BOOT SIGNAL - JACOB wire HSELEXT; wire [55:0] HADDR; wire [63:0] HWDATA; @@ -240,7 +239,7 @@ module fpgaTop wallypipelinedsoc #(P) wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, - .HSELEXTSDC, .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), + .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index dad558c19..c3414352f 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -168,9 +168,9 @@ module uncore import cvw::*; #(parameter cvw_t P)( if (P.SDC_SUPPORTED == 1) begin : sdc spi_apb #(P) sdc( - .PCLK, .PRESETN, .PSEL(.PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, + .PCLK, .PRESETn, .PSEL(PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), - .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(.SDCIntr)); + .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr)); end else begin : sdc assign SDCCmd = '0; assign SDCCD = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; end diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index af9f0ff26..7ad173b78 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -35,7 +35,6 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( input logic [P.AHBW-1:0] HRDATAEXT, input logic HREADYEXT, HRESPEXT, output logic HSELEXT, - output logic HSELEXTSDC, // outputs to external memory, shared with uncore memory output logic HCLK, HRESETn, output logic [P.PA_BITS-1:0] HADDR, @@ -86,11 +85,11 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( if (P.BUS_SUPPORTED) begin : uncoregen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 uncore #(P) uncore(.HCLK, .HRESETn, .TIMECLK, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT, - .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC, + .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); end else begin - assign {HRDATA, HREADY, HRESP, HSELEXT, HSELEXTSDC, MTimerInt, MSwInt, MExtInt, SExtInt, + assign {HRDATA, HREADY, HRESP, HSELEXT, MTimerInt, MSwInt, MExtInt, SExtInt, MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; end From 6c212ebf0efa671199abefcd2a64863dbf495e73 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 17:39:38 -0500 Subject: [PATCH 128/163] Changes are confirmed to work on the FPGA. --- src/rvvi/rvvisynth.sv | 2 +- testbench/testbench.sv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index 83c865529..f42e9c1a8 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -28,7 +28,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module rvvisynth import cvw::*; #(parameter cvw_t P, - parameter integer MAX_CSRS = 3, + parameter integer MAX_CSRS = 5, parameter integer TOTAL_CSRS = 36)( input logic clk, reset, input logic StallE, StallM, StallW, FlushE, FlushM, FlushW, diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 4885a6121..318d3d016 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -604,7 +604,7 @@ module testbench; end if(P.RVVI_SYNTH_SUPPORTED) begin : rvvi_synth - localparam MAX_CSRS = 3; + localparam MAX_CSRS = 5; logic valid; logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; From 9404a339ee202e24162f377ac626a953170f323f Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Tue, 23 Jul 2024 17:44:37 -0500 Subject: [PATCH 129/163] Handled all remaining verilator warnings in the rvvi synth code. Now it's time to take on the verilog-ethernet warnings. --- src/rvvi/rvvisynth.sv | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rvvi/rvvisynth.sv b/src/rvvi/rvvisynth.sv index f42e9c1a8..0c0214b3f 100644 --- a/src/rvvi/rvvisynth.sv +++ b/src/rvvi/rvvisynth.sv @@ -88,6 +88,9 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, {FPRWen, GPRWen} == 2'b10 ? {XLENZeros, 5'b0, FPRValue, FPRAddr} : '0; + /* verilator lint_off UNOPTFLAT */ + // For some reason verilator complains about CSRWenFilterMatrix being in a circular loop when it is not. + // the CSRs are complex // 1. we need to get the CSR values // 2. we check if the CSR value changes by registering the value then XORing with the old value. @@ -121,9 +124,12 @@ module rvvisynth import cvw::*; #(parameter cvw_t P, always_comb begin CSRCountShort = '0; for(index2 = 0; index2 < MAX_CSRS; index2++) begin + /* verilator lint_off WIDTHEXPAND */ CSRCountShort += EnabledCSRs[index2]; + /* verilator lint_on WIDTHEXPAND */ end end + /* verilator lint_on UNOPTFLAT */ assign CSRCount = {{{12-MAX_CSRS}{1'b0}}, CSRCountShort}; assign rvvi = {CSRs, Registers, Required}; From 27f89fcdbdcc50a2c3021cdd6a6c5eb3b323be1b Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 24 Jul 2024 10:13:03 -0500 Subject: [PATCH 130/163] Updated verilog-ethernet to remove all verilator warnings or at least suppress them. --- addins/verilog-ethernet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addins/verilog-ethernet b/addins/verilog-ethernet index 471394b80..c180b22ed 160000 --- a/addins/verilog-ethernet +++ b/addins/verilog-ethernet @@ -1 +1 @@ -Subproject commit 471394b80c95a4859cd55a0f253d5ea502371e98 +Subproject commit c180b22ed5f4112d0ef35b2c5ac1acc45f9ebb5d From b1a711ae0f87622ce7bf484e06979c88d4f31678 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 24 Jul 2024 12:47:50 -0500 Subject: [PATCH 131/163] Converted fpga's rvvi from a config option to a testbench/fpga top level parameter and is envoked by passing --rvvi to wsim. --- bin/wsim | 4 ++++ config/derivlist.txt | 4 ---- config/rv32e/config.vh | 5 ----- config/rv32gc/config.vh | 5 ----- config/rv32i/config.vh | 5 ----- config/rv32imc/config.vh | 5 ----- config/rv64gc/config.vh | 5 ----- config/rv64i/config.vh | 5 ----- config/shared/parameter-defs.vh | 5 +---- fpga/generator/wally.tcl | 4 ++-- fpga/src/fpgaTopArtyA7.sv | 8 +++++--- src/cvw.sv | 4 ---- src/rvvi/packetizer.sv | 9 ++++++--- testbench/testbench.sv | 12 ++++++------ 14 files changed, 24 insertions(+), 56 deletions(-) diff --git a/bin/wsim b/bin/wsim index b70d0e26f..b2288deb4 100755 --- a/bin/wsim +++ b/bin/wsim @@ -33,6 +33,7 @@ parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_ parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") parser.add_argument("--locksteplog", "-b", help="Retired instruction number to be begin logging.", default=0) parser.add_argument("--covlog", "-d", help="Log coverage after n instructions.", default=0) +parser.add_argument("--rvvi", "-r", help="Simulate rvvi hardware interface and ethernet.", action="store_true") args = parser.parse_args() print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'") ElfFile="" @@ -64,6 +65,9 @@ if (args.gui or args.ccov or args.fcov or args.lockstep): if (args.vcd): args.args += " -DMAKEVCD=1" +if (args.rvvi): + args.args += " -GRVVI_SYNTH_SUPPORTED=1" + # if lockstep is enabled, then we need to pass the Imperas lockstep arguments if(int(args.locksteplog) >= 1): EnableLog = 1 else: EnableLog = 0 diff --git a/config/derivlist.txt b/config/derivlist.txt index 048adcb21..1edd20b7b 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -57,10 +57,6 @@ EXT_MEM_RANGE 64'h0FFFFFFF SDC_SUPPORTED 1 PLIC_SDC_ID 32'd20 BPRED_SIZE 32'd12 -RVVI_SYNTH_SUPPORTED 1 -RVVI_INIT_TIME_OUT 32'd100000000 -RVVI_PACKET_DELAY 32'd400 - # The syn configurations are trimmed down for faster synthesis. deriv syn_rv32e rv32e diff --git a/config/rv32e/config.vh b/config/rv32e/config.vh index 1234bbcdf..4ec0123d1 100644 --- a/config/rv32e/config.vh +++ b/config/rv32e/config.vh @@ -225,9 +225,4 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; -// debug tools -localparam logic RVVI_SYNTH_SUPPORTED = 0; -localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; -localparam [31:0] RVVI_PACKET_DELAY = 32'd2; - `include "config-shared.vh" diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index 9f5809383..c861759d9 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -225,9 +225,4 @@ localparam DIVCOPIES = 32'd2; // Memory synthesis configuration localparam logic USE_SRAM = 0; -// debug tools -localparam logic RVVI_SYNTH_SUPPORTED = 0; -localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; -localparam [31:0] RVVI_PACKET_DELAY = 32'd2; - `include "config-shared.vh" diff --git a/config/rv32i/config.vh b/config/rv32i/config.vh index 6bfea805e..01818afc2 100644 --- a/config/rv32i/config.vh +++ b/config/rv32i/config.vh @@ -225,9 +225,4 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; -// debug tools -localparam logic RVVI_SYNTH_SUPPORTED = 0; -localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; -localparam [31:0] RVVI_PACKET_DELAY = 32'd2; - `include "config-shared.vh" diff --git a/config/rv32imc/config.vh b/config/rv32imc/config.vh index 3918c702c..05a8fd242 100644 --- a/config/rv32imc/config.vh +++ b/config/rv32imc/config.vh @@ -225,9 +225,4 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; -// debug tools -localparam logic RVVI_SYNTH_SUPPORTED = 0; -localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; -localparam [31:0] RVVI_PACKET_DELAY = 32'd2; - `include "config-shared.vh" diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index 86036aaa7..b8ed8dc47 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -225,9 +225,4 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; -// debug tools -localparam logic RVVI_SYNTH_SUPPORTED = 0; -localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; -localparam [31:0] RVVI_PACKET_DELAY = 32'd2; - `include "config-shared.vh" diff --git a/config/rv64i/config.vh b/config/rv64i/config.vh index 0e13f9ea1..94360877f 100644 --- a/config/rv64i/config.vh +++ b/config/rv64i/config.vh @@ -225,9 +225,4 @@ localparam DIVCOPIES = 32'd4; // Memory synthesis configuration localparam logic USE_SRAM = 0; -// debug tools -localparam logic RVVI_SYNTH_SUPPORTED = 0; -localparam [31:0] RVVI_INIT_TIME_OUT = 32'd4; -localparam [31:0] RVVI_PACKET_DELAY = 32'd2; - `include "config-shared.vh" diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index 14b5ee45c..c80b00232 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -200,9 +200,6 @@ localparam cvw_t P = '{ DURLEN : DURLEN, DIVb : DIVb, DIVBLEN : DIVBLEN, - INTDIVb : INTDIVb, - RVVI_SYNTH_SUPPORTED : RVVI_SYNTH_SUPPORTED, - RVVI_INIT_TIME_OUT : RVVI_INIT_TIME_OUT, - RVVI_PACKET_DELAY : RVVI_PACKET_DELAY + INTDIVb : INTDIVb }; diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index 9df775646..93c2788a2 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -89,8 +89,8 @@ report_clock_interaction -file re write_verilog -force -mode funcsim sim/syn-funcsim.v if {$board=="ArtyA7"} { - source ../constraints/small-debug.xdc - #source ../constraints/small-debug-rvvi.xdc + #source ../constraints/small-debug.xdc + source ../constraints/small-debug-rvvi.xdc } else { # source ../constraints/vcu-small-debug.xdc diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 314b141a5..9413cedec 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -28,7 +28,7 @@ import cvw::*; -module fpgaTop +module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 0) (input default_100mhz_clk, (* mark_debug = "true" *) input resetn, input south_reset, @@ -1117,9 +1117,11 @@ module fpgaTop (* mark_debug = "true" *) logic IlaTrigger; - if(P.RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + if(RVVI_SYNTH_SUPPORTED) begin : rvvi_synth localparam MAX_CSRS = 3; localparam TOTAL_CSRS = 36; + localparam [31:0] RVVI_INIT_TIME_OUT = 32'd100000000; + localparam [31:0] RVVI_PACKET_DELAY = 32'd400; // pipeline controlls logic StallE, StallM, StallW, FlushE, FlushM, FlushW; @@ -1218,7 +1220,7 @@ module fpgaTop logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; - packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, + packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); eth_mac_mii_fifo #(.TARGET("XILINX"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), diff --git a/src/cvw.sv b/src/cvw.sv index 7a64be7ba..ed0493484 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -296,10 +296,6 @@ typedef struct packed { int DIVBLEN ; // integer division/remainder constants int INTDIVb ; -// debug tools - logic RVVI_SYNTH_SUPPORTED; - logic [31:0] RVVI_INIT_TIME_OUT; - logic [31:0] RVVI_PACKET_DELAY; } cvw_t; endpackage diff --git a/src/rvvi/packetizer.sv b/src/rvvi/packetizer.sv index 54dc9a27f..cd3103fa4 100644 --- a/src/rvvi/packetizer.sv +++ b/src/rvvi/packetizer.sv @@ -28,7 +28,10 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module packetizer import cvw::*; #(parameter cvw_t P, - parameter integer MAX_CSRS)( + parameter integer MAX_CSRS, + parameter logic [31:0] RVVI_INIT_TIME_OUT = 32'd4, + parameter logic [31:0] RVVI_PACKET_DELAY = 32'd2 +)( input logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi, input logic valid, input logic m_axi_aclk, m_axi_aresetn, @@ -100,8 +103,8 @@ module packetizer import cvw::*; #(parameter cvw_t P, // have to count at least 250 ms after reset pulled to wait for the phy to actually be ready // at 20MHz 250 ms is 250e-3 / (1/20e6) = 5,000,000. counter #(32) rstcounter(m_axi_aclk, RstCountRst, RstCountEn, RstCount); - assign CountFlag = RstCount == P.RVVI_INIT_TIME_OUT; - assign DelayFlag = RstCount == P.RVVI_PACKET_DELAY; + assign CountFlag = RstCount == RVVI_INIT_TIME_OUT; + assign DelayFlag = RstCount == RVVI_PACKET_DELAY; counter #(32) framecounter(m_axi_aclk, ~m_axi_aresetn, (RvviAxiWready & RvviAxiWlast), FrameCount); diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 318d3d016..a32a294d0 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -33,9 +33,6 @@ `include "idv/idv.svh" `endif -// *** bug replace with config? -`define RVVI_SYNTH_SUPPORTED 1 - import cvw::*; module testbench; @@ -46,6 +43,7 @@ module testbench; parameter BPRED_LOGGER=0; parameter I_CACHE_ADDR_LOGGER=0; parameter D_CACHE_ADDR_LOGGER=0; + parameter RVVI_SYNTH_SUPPORTED=0; `ifdef USE_IMPERAS_DV import idvPkg::*; @@ -603,9 +601,11 @@ module testbench; clk = 1'b1; # 5; clk = 1'b0; # 5; end - if(P.RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + if(RVVI_SYNTH_SUPPORTED) begin : rvvi_synth localparam MAX_CSRS = 5; - logic valid; + localparam logic [31:0] RVVI_INIT_TIME_OUT = 32'd4; + localparam logic [31:0] RVVI_PACKET_DELAY = 32'd2; + logic valid; logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; localparam TOTAL_CSRS = 36; @@ -702,7 +702,7 @@ module testbench; logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; - packetizer #(P, MAX_CSRS) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, + packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), From d0a5b278b78b26e5c26259bec93d4460706711e9 Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 24 Jul 2024 13:10:57 -0500 Subject: [PATCH 132/163] Factored out the rvvi testbench code into rvvitbwrapper. --- fpga/src/fpgaTopArtyA7.sv | 2 +- testbench/common/rvvitbwrapper.sv | 170 ++++++++++++++++++++++++++++++ testbench/testbench.sv | 126 +--------------------- 3 files changed, 174 insertions(+), 124 deletions(-) create mode 100644 testbench/common/rvvitbwrapper.sv diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 9413cedec..827ca1438 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -28,7 +28,7 @@ import cvw::*; -module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 0) +module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1) (input default_100mhz_clk, (* mark_debug = "true" *) input resetn, input south_reset, diff --git a/testbench/common/rvvitbwrapper.sv b/testbench/common/rvvitbwrapper.sv new file mode 100644 index 000000000..708cd0e7b --- /dev/null +++ b/testbench/common/rvvitbwrapper.sv @@ -0,0 +1,170 @@ +/////////////////////////////////////////// +// loggers.sv +// +// Written: Rose Thompson ross1728@gmail.com +// Modified: 24 July 2024 +// +// Purpose: Wraps all the synthesizable rvvi hardware into a single module for the testbench. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module rvvitbwrapper import cvw::*; #(parameter cvw_t P, + parameter MAX_CSRS = 5, + parameter logic [31:0] RVVI_INIT_TIME_OUT = 32'd4, + parameter logic [31:0] RVVI_PACKET_DELAY = 32'd2)( + input logic clk, + input logic reset, + output logic RVVIStall, + input logic mii_tx_clk, + output logic [3:0] mii_txd, + output logic mii_tx_en, mii_tx_er, + input logic mii_rx_clk, + input logic [3:0] mii_rxd, + input logic mii_rx_dv, + input logic mii_rx_er +); + + logic valid; + logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; + + localparam TOTAL_CSRS = 36; + + // pipeline controlls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + + // axi 4 write data channel + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + logic MiiTxEnDelay; + logic EthernetTXCounterEn; + logic [31:0] EthernetTXCount; + + assign StallE = dut.core.StallE; + assign StallM = dut.core.StallM; + assign StallW = dut.core.StallW; + assign FlushE = dut.core.FlushE; + assign FlushM = dut.core.FlushM; + assign FlushW = dut.core.FlushW; + assign InstrValidM = dut.core.ieu.InstrValidM; + assign InstrRawD = dut.core.ifu.InstrRawD; + assign PCM = dut.core.ifu.PCM; + assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = dut.core.TrapM; + assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = dut.core.ieu.dp.regf.a3; + assign GPRWen = dut.core.ieu.dp.regf.we3; + assign GPRValue = dut.core.ieu.dp.regf.wd3; + assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; + assign FPRWen = dut.core.fpu.fpu.fregfile.we4; + assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + + rvvisynth #(P, MAX_CSRS, TOTAL_CSRS) rvvisynth(.clk, .reset, .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); + + packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, + .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); + + eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), + .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), + .rx_axis_tlast(), .rx_axis_tuser(), + + .mii_rx_clk(clk), + .mii_rxd('0), + .mii_rx_dv('0), + .mii_rx_er('0), + .mii_tx_clk(clk), + .mii_txd, + .mii_tx_en, + .mii_tx_er, + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1)); + + flopr #(1) txedgereg(clk, reset, mii_tx_en, MiiTxEnDelay); + assign EthernetTXCounterEn = ~mii_tx_en & MiiTxEnDelay; + counter #(32) ethernexttxcounter(clk, reset, EthernetTXCounterEn, EthernetTXCount); + +endmodule + + + diff --git a/testbench/testbench.sv b/testbench/testbench.sv index a32a294d0..55bb35843 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -605,133 +605,13 @@ module testbench; localparam MAX_CSRS = 5; localparam logic [31:0] RVVI_INIT_TIME_OUT = 32'd4; localparam logic [31:0] RVVI_PACKET_DELAY = 32'd2; - logic valid; - logic [187+(3*P.XLEN) + MAX_CSRS*(P.XLEN+12)-1:0] rvvi; - - localparam TOTAL_CSRS = 36; - - // pipeline controlls - logic StallE, StallM, StallW, FlushE, FlushM, FlushW; - // required - logic [P.XLEN-1:0] PCM; - logic InstrValidM; - logic [31:0] InstrRawD; - logic [63:0] Mcycle, Minstret; - logic TrapM; - logic [1:0] PrivilegeModeW; - // registers gpr and fpr - logic GPRWen, FPRWen; - logic [4:0] GPRAddr, FPRAddr; - logic [P.XLEN-1:0] GPRValue, FPRValue; - logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; - - assign StallE = dut.core.StallE; - assign StallM = dut.core.StallM; - assign StallW = dut.core.StallW; - assign FlushE = dut.core.FlushE; - assign FlushM = dut.core.FlushM; - assign FlushW = dut.core.FlushW; - assign InstrValidM = dut.core.ieu.InstrValidM; - assign InstrRawD = dut.core.ifu.InstrRawD; - assign PCM = dut.core.ifu.PCM; - assign Mcycle = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; - assign Minstret = dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; - assign TrapM = dut.core.TrapM; - assign PrivilegeModeW = dut.core.priv.priv.privmode.PrivilegeModeW; - assign GPRAddr = dut.core.ieu.dp.regf.a3; - assign GPRWen = dut.core.ieu.dp.regf.we3; - assign GPRValue = dut.core.ieu.dp.regf.wd3; - assign FPRAddr = dut.core.fpu.fpu.fregfile.a4; - assign FPRWen = dut.core.fpu.fpu.fregfile.we4; - assign FPRValue = dut.core.fpu.fpu.fregfile.wd4; - - assign CSRArray[0] = dut.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 - assign CSRArray[1] = dut.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 - assign CSRArray[2] = dut.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 - assign CSRArray[3] = dut.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 - assign CSRArray[4] = dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 - assign CSRArray[5] = dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 - assign CSRArray[6] = dut.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 - assign CSRArray[7] = dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 - assign CSRArray[8] = dut.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 - assign CSRArray[9] = dut.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 - assign CSRArray[10] = dut.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 - assign CSRArray[11] = dut.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A - assign CSRArray[12] = dut.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 - assign CSRArray[13] = dut.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 - assign CSRArray[14] = dut.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 - assign CSRArray[15] = dut.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 - assign CSRArray[16] = 0; // 12'hF11 - assign CSRArray[17] = 0; // 12'hF12 - assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 - assign CSRArray[19] = 0; // 12'hF15 - assign CSRArray[20] = 0; // 12'h34A - // supervisor CSRs - assign CSRArray[21] = dut.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 - assign CSRArray[22] = dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 - assign CSRArray[23] = dut.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 - assign CSRArray[24] = dut.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 - assign CSRArray[25] = dut.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 - assign CSRArray[26] = dut.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A - assign CSRArray[27] = dut.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 - assign CSRArray[28] = dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 - assign CSRArray[29] = dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 - assign CSRArray[30] = dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 - assign CSRArray[31] = dut.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & dut.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 - assign CSRArray[32] = dut.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D - // user CSRs - assign CSRArray[33] = dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 - assign CSRArray[34] = dut.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 - assign CSRArray[35] = {dut.core.priv.priv.csr.csru.csru.FRM_REGW, dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 - - rvvisynth #(P, MAX_CSRS, TOTAL_CSRS) rvvisynth(.clk, .reset, .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, - .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, - .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, - .valid, .rvvi); - - // axi 4 write data channel - logic [31:0] RvviAxiWdata; - logic [3:0] RvviAxiWstrb; - logic RvviAxiWlast; - logic RvviAxiWvalid; - logic RvviAxiWready; logic [3:0] mii_txd; logic mii_tx_en, mii_tx_er; - - logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; - logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; - - packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(clk), .m_axi_aresetn(~reset), .RVVIStall, - .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); - - eth_mac_mii_fifo #("GENERIC", "BUFG", 32) ethernet(.rst(reset), .logic_clk(clk), .logic_rst(reset), - .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), - .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(), .rx_axis_tkeep(), .rx_axis_tvalid(), .rx_axis_tready(1'b1), - .rx_axis_tlast(), .rx_axis_tuser(), - - .mii_rx_clk(clk), - .mii_rxd('0), - .mii_rx_dv('0), - .mii_rx_er('0), - .mii_tx_clk(clk), - .mii_txd, - .mii_tx_en, - .mii_tx_er, - - // status - .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, - .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, - .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) - ); - - logic MiiTxEnDelay; - logic EthernetTXCounterEn; - logic [31:0] EthernetTXCount; - flopr #(1) txedgereg(clk, reset, mii_tx_en, MiiTxEnDelay); - assign EthernetTXCounterEn = ~mii_tx_en & MiiTxEnDelay; - counter #(32) ethernexttxcounter(clk, reset, EthernetTXCounterEn, EthernetTXCount); + rvvitbwrapper #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) + rvvitbwrapper(.clk, .reset, .RVVIStall, .mii_tx_clk(clk), .mii_txd, .mii_tx_en, .mii_tx_er, + .mii_rx_clk(clk), .mii_rxd('0), .mii_rx_dv('0), .mii_rx_er('0)); end else begin assign RVVIStall = '0; end From 5cae55561e3a819dd4b9ec3d19c0620b8ded71fd Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 24 Jul 2024 13:30:25 -0500 Subject: [PATCH 133/163] Removed unused file. --- fpga/rvvidaemon/send-copy.c | 133 ------------------------------------ 1 file changed, 133 deletions(-) delete mode 100644 fpga/rvvidaemon/send-copy.c diff --git a/fpga/rvvidaemon/send-copy.c b/fpga/rvvidaemon/send-copy.c deleted file mode 100644 index 5d7f85ee8..000000000 --- a/fpga/rvvidaemon/send-copy.c +++ /dev/null @@ -1,133 +0,0 @@ - -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - */ - -#include <arpa/inet.h> -#include <linux/if_packet.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netinet/ether.h> -#include <unistd.h> - -#define DEST_MAC0 0x43 -#define DEST_MAC1 0x68 -#define DEST_MAC2 0x11 -#define DEST_MAC3 0x11 -#define DEST_MAC4 0x02 -#define DEST_MAC5 0x45 - -#define SRC_MAC0 0x54 -#define SRC_MAC1 0x16 -#define SRC_MAC2 0x00 -#define SRC_MAC3 0x00 -#define SRC_MAC4 0x54 -#define SRC_MAC5 0x8F - -#define DEFAULT_IF "eth0" -#define BUF_SIZ 1024 -#define ETHER_TYPE 0x5c00 // The type defined in packetizer.sv - -int main(int argc, char *argv[]) -{ - int sockfd; - struct ifreq if_idx; - struct ifreq if_mac; - int tx_len = 0; - char sendbuf[BUF_SIZ]; - struct ether_header *eh = (struct ether_header *) sendbuf; - struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header)); - struct sockaddr_ll socket_address; - char ifName[IFNAMSIZ]; - - /* Get interface name */ - if (argc > 1) - strcpy(ifName, argv[1]); - else - strcpy(ifName, DEFAULT_IF); - - /* Open RAW socket to send on */ - //if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { - if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) { - perror("socket"); - } - - /* Get the index of the interface to send on */ - memset(&if_idx, 0, sizeof(struct ifreq)); - strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1); - if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) - perror("SIOCGIFINDEX"); - /* Get the MAC address of the interface to send on */ - memset(&if_mac, 0, sizeof(struct ifreq)); - strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1); - if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0) - perror("SIOCGIFHWADDR"); - - /* Construct the Ethernet header */ - memset(sendbuf, 0, BUF_SIZ); - /* Ethernet header */ - /* eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; */ - /* eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; */ - /* eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; */ - /* eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; */ - /* eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; */ - /* eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; */ - eh->ether_shost[0] = SRC_MAC0; - eh->ether_shost[1] = SRC_MAC1; - eh->ether_shost[2] = SRC_MAC2; - eh->ether_shost[3] = SRC_MAC3; - eh->ether_shost[4] = SRC_MAC4; - eh->ether_shost[5] = SRC_MAC5; - eh->ether_dhost[0] = DEST_MAC0; - eh->ether_dhost[1] = DEST_MAC1; - eh->ether_dhost[2] = DEST_MAC2; - eh->ether_dhost[3] = DEST_MAC3; - eh->ether_dhost[4] = DEST_MAC4; - eh->ether_dhost[5] = DEST_MAC5; - /* Ethertype field */ - //eh->ether_type = htons(ETH_P_IP); - eh->ether_type = htons(ETHER_TYPE); - tx_len += sizeof(struct ether_header); - - /* Packet data */ - sendbuf[tx_len++] = 0xde; - sendbuf[tx_len++] = 0xad; - sendbuf[tx_len++] = 0xbe; - sendbuf[tx_len++] = 0xef; - - /* Index of the network device */ - socket_address.sll_ifindex = if_idx.ifr_ifindex; - /* Address length*/ - socket_address.sll_halen = ETH_ALEN; - /* Destination MAC */ - socket_address.sll_addr[0] = DEST_MAC0; - socket_address.sll_addr[1] = DEST_MAC1; - socket_address.sll_addr[2] = DEST_MAC2; - socket_address.sll_addr[3] = DEST_MAC3; - socket_address.sll_addr[4] = DEST_MAC4; - socket_address.sll_addr[5] = DEST_MAC5; - - int i; - printf("buffer: "); - for(i=0;i<tx_len;i++){ - printf("%02hhx ", sendbuf[i]); - } - printf("\n"); - printf("sockfd %x\n", sockfd); - - /* Send packet */ - if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0){ - printf("Send failed\n"); - }else { - printf("send success!\n"); - } - close(sockfd); - return 0; -} From ce61429bdfdd7842e8620019229ebb71e0a2536b Mon Sep 17 00:00:00 2001 From: Rose Thompson <ross1728@gmail.com> Date: Wed, 24 Jul 2024 13:32:46 -0500 Subject: [PATCH 134/163] Fixed the reset bug in wallyTracer. --- testbench/common/wallyTracer.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testbench/common/wallyTracer.sv b/testbench/common/wallyTracer.sv index 8c72a6816..80f7af651 100644 --- a/testbench/common/wallyTracer.sv +++ b/testbench/common/wallyTracer.sv @@ -274,7 +274,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi); // Initially connecting the writeback stage signals, but may need to use M stage // and gate on ~FlushW. - assign valid = InstrValidW & ~StallW; + assign valid = InstrValidW & ~StallW & ~reset; assign rvvi.clk = clk; assign rvvi.valid[0][0] = valid; assign rvvi.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order From 0107a400d175a06c653cfd824e83ef2f602d1836 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 24 Jul 2024 22:43:16 -0500 Subject: [PATCH 135/163] Added uart header to gpt.c. --- fpga/zsbl/gpt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 90948935b..c308ea878 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -1,5 +1,6 @@ #include "gpt.h" #include "boot.h" +#include "uart.h" #include <stddef.h> /* PSUEDOCODE From 286d80de7e45c6cbb53b4dfacd37c202876e9c84 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 24 Jul 2024 22:43:47 -0500 Subject: [PATCH 136/163] Initialized UART with Arty frequency and baud rate. Will make this dynamic in the future --- fpga/zsbl/boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 786879c49..e8065f732 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -96,7 +96,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { int ret = 0; // Initialize UART for messages - init_uart(); + init_uart(20000000, 115200); // Print the wally banner print_uart(BANNER); From d15be492cb5cce505f04ef9c450915a8b668fb45 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 24 Jul 2024 22:44:27 -0500 Subject: [PATCH 137/163] Masked lower byte when writing to DLL. --- fpga/zsbl/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index be3270e28..7ff40e516 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -35,7 +35,7 @@ void init_uart(uint32_t freq, uint32_t baud) write_reg_u8(UART_IER, 0x00); // Disable all interrupts write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) - write_reg_u8(UART_DLL, divisor); // divisor (lo byte) + write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte) write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold From 2caf9e93be6693a0ff45056b97ee003e83ab24c8 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 24 Jul 2024 22:46:24 -0500 Subject: [PATCH 138/163] Removed old axi IP from fpga Makefile. Added sed for data.mem file loaded into uncore ram. --- fpga/generator/Makefile | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index df4ed0e2a..7865d33ee 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -1,14 +1,14 @@ dst := IP # vcu118 -#export XILINX_PART := xcvu9p-flga2104-2L-e -#export XILINX_BOARD := xilinx.com:vcu118:part0:2.4 -#export board := vcu118 +# export XILINX_PART := xcvu9p-flga2104-2L-e +# export XILINX_BOARD := xilinx.com:vcu118:part0:2.4 +# export board := vcu118 # vcu108 -#export XILINX_PART := xcvu095-ffva2104-2-e -#export XILINX_BOARD := xilinx.com:vcu108:part0:1.2 -#export board := vcu108 +# export XILINX_PART := xcvu095-ffva2104-2-e +# export XILINX_BOARD := xilinx.com:vcu108:part0:1.7 +# export board := vcu108 # Arty A7 export XILINX_PART := xc7a100tcsg324-1 @@ -40,11 +40,11 @@ IP_Arty: $(dst)/xlnx_proc_sys_reset.log \ $(dst)/xlnx_ddr3-$(board).log \ $(dst)/xlnx_mmcm.log \ $(dst)/xlnx_axi_clock_converter.log \ - $(dst)/xlnx_ahblite_axi_bridge.log \ - $(dst)/xlnx_axi_crossbar.log \ - $(dst)/xlnx_axi_dwidth_conv_32to64.log \ - $(dst)/xlnx_axi_dwidth_conv_64to32.log \ - $(dst)/xlnx_axi_prtcl_conv.log + $(dst)/xlnx_ahblite_axi_bridge.log +#$(dst)/xlnx_axi_crossbar.log \ +#$(dst)/xlnx_axi_dwidth_conv_32to64.log \ +#$(dst)/xlnx_axi_dwidth_conv_64to32.log \ +#$(dst)/xlnx_axi_prtcl_conv.log PreProcessFiles: @@ -59,6 +59,7 @@ PreProcessFiles: # This line allows the Bootloader to be loaded in a Block RAM on the FPGA sed -i "s/bit \[DATA_WIDTH-1:0\].*ROM.*/(\* rom_style=\"block\" \*) &/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv + sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/ram1p1rwbe.sv $(dst)/%.log: %.tcl mkdir -p IP From ebdf25a53b0936b04adcd9e17598acaed111e4bd Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 24 Jul 2024 22:47:15 -0500 Subject: [PATCH 139/163] Commented out references to old axi IP from wally.tcl. --- fpga/generator/wally.tcl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index eff0a6cb9..9acdad4b6 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -27,10 +27,10 @@ read_ip IP/xlnx_proc_sys_reset.srcs/sources_1/ip/xlnx_proc_sys_reset/xlnx_proc_s read_ip IP/xlnx_ahblite_axi_bridge.srcs/sources_1/ip/xlnx_ahblite_axi_bridge/xlnx_ahblite_axi_bridge.xci read_ip IP/xlnx_axi_clock_converter.srcs/sources_1/ip/xlnx_axi_clock_converter/xlnx_axi_clock_converter.xci # Added crossbar - Jacob Pease <2023-01-12 Thu> -read_ip IP/xlnx_axi_crossbar.srcs/sources_1/ip/xlnx_axi_crossbar/xlnx_axi_crossbar.xci -read_ip IP/xlnx_axi_dwidth_conv_32to64.srcs/sources_1/ip/xlnx_axi_dwidth_conv_32to64/xlnx_axi_dwidth_conv_32to64.xci -read_ip IP/xlnx_axi_dwidth_conv_64to32.srcs/sources_1/ip/xlnx_axi_dwidth_conv_64to32/xlnx_axi_dwidth_conv_64to32.xci -read_ip IP/xlnx_axi_prtcl_conv.srcs/sources_1/ip/xlnx_axi_prtcl_conv/xlnx_axi_prtcl_conv.xci +#read_ip IP/xlnx_axi_crossbar.srcs/sources_1/ip/xlnx_axi_crossbar/xlnx_axi_crossbar.xci +#read_ip IP/xlnx_axi_dwidth_conv_32to64.srcs/sources_1/ip/xlnx_axi_dwidth_conv_32to64/xlnx_axi_dwidth_conv_32to64.xci +#read_ip IP/xlnx_axi_dwidth_conv_64to32.srcs/sources_1/ip/xlnx_axi_dwidth_conv_64to32/xlnx_axi_dwidth_conv_64to32.xci +#read_ip IP/xlnx_axi_prtcl_conv.srcs/sources_1/ip/xlnx_axi_prtcl_conv/xlnx_axi_prtcl_conv.xci if {$board=="ArtyA7"} { read_ip IP/xlnx_ddr3.srcs/sources_1/ip/xlnx_ddr3/xlnx_ddr3.xci @@ -89,8 +89,8 @@ report_clock_interaction -file re write_verilog -force -mode funcsim sim/syn-funcsim.v if {$board=="ArtyA7"} { - source ../constraints/small-debug.xdc - + #source ../constraints/small-debug.xdc + source ../constraints/medium-debug.xdc } else { # source ../constraints/vcu-small-debug.xdc source ../constraints/debug6.xdc From 0dae881a0dadd83d9bb5a5a139819be9664f618d Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 24 Jul 2024 22:48:31 -0500 Subject: [PATCH 140/163] Fixed SDCCLK name discrepency. --- fpga/constraints/constraints-ArtyA7.xdc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index f466b0c30..4e156601b 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -101,7 +101,7 @@ set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports { set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[0]}] -set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCClk}] +set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}] set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] From f7dd49cc6cef8f075f8dc5ceabf1d913f07caad8 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 25 Jul 2024 06:59:58 -0700 Subject: [PATCH 141/163] Issue #894: trap on floating-point ops with reserved rounding modes --- src/fpu/fctrl.sv | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 8595fd29e..eed90ddcf 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -81,6 +81,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( logic [1:0] Fmt, Fmt2; // format - before possible reduction logic SupportedFmt; // is the format supported logic SupportedFmt2; // is the source format supported for fp -> fp + logic SupportedRM; // is the rounding mode supported logic FCvtIntD, FCvtIntM; // convert to integer operation logic ZfaD; // Zfa variants of instructions logic ZfaFRoundNXD; // Zfa froundnx instruction @@ -93,14 +94,16 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( (Fmt == 2'b10 & P.ZFH_SUPPORTED) | (Fmt == 2'b11 & P.Q_SUPPORTED)); assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) | (Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_SUPPORTED)); + // rounding modes 5 and 6 are reserved. Rounding mode 7 is dynamic, and is reserved if FRM is 5, 6, or 7 + assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))); // decode the instruction // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa_FroundNX always_comb if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; - else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt) - ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // for anything other than loads and stores, check for supported format + else if (OpD != 7'b0000111 & OpD != 7'b0100111 & (~SupportedFmt | ~SupportedRM)) + ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // for anything other than loads and stores, check for supported format and rounding mode else begin ControlsD = `FCTRLW'b0_0_00_00_000_0_1_0_0_0; // default: non-implemented instruction /* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed From 5bf7250687ddde2fb31062a2182921cab81c3a96 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 25 Jul 2024 09:09:13 -0700 Subject: [PATCH 142/163] Issue #894: trap on floating-point ops with reserved rounding modes: detect Zfa flt --- src/fpu/fctrl.sv | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index eed90ddcf..ab9cad093 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -95,8 +95,11 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) | (Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_SUPPORTED)); // rounding modes 5 and 6 are reserved. Rounding mode 7 is dynamic, and is reserved if FRM is 5, 6, or 7 - assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))); - + assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))) | + (OpD == 7'b1010011 & Funct3D == 3'b101 & Funct7D[6:2] == 5'b10100 & P.ZFA_SUPPORTED); // Zfa fltq has a funny rounding mode + /*assign SupportedRM = ~(Funct3D == 3'b101 | Funct3D == 3'b110 | (Funct3D == 3'b111 & (FRM_REGW == 3'b101 | FRM_REGW == 3'b110 | FRM_REGW == 3'b111))) | + (OpD == 7'b1010011 & P.ZFA_SUPPORTED); +*/ // decode the instruction // FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt_Zfa_FroundNX always_comb From 336a413f3185b089223a75d3b1d43e8f12465611 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Thu, 25 Jul 2024 11:19:15 -0500 Subject: [PATCH 143/163] Added ability to split boot.memfile into boot.mem and data.mem. --- fpga/zsbl/Makefile | 9 ++++++-- src/generic/mem/ram1p1rwbe.sv | 23 +++++++++++++++++---- src/uncore/uncore.sv | 10 ++++----- testbench/testbench.sv | 39 ++++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/fpga/zsbl/Makefile b/fpga/zsbl/Makefile index 37323b813..85bfc67eb 100644 --- a/fpga/zsbl/Makefile +++ b/fpga/zsbl/Makefile @@ -17,6 +17,7 @@ OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) TARGETDIR := bin TARGET := $(TARGETDIR)/boot +MEMFILES := $(TARGETDIR/boot.mem $(TARGETDIR)/data.mem ROOT := .. LIBRARY_DIRS := LIBRARY_FILES := @@ -37,7 +38,7 @@ AR=riscv64-unknown-elf-ar #Default Make -all: directories $(TARGET).memfile +all: directories $(TARGET).memfile #Remake remake: clean all @@ -48,7 +49,7 @@ directories: @mkdir -p $(BUILDDIR) clean: - rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump boot.mem data.mem #Needed for building additional library projects @@ -112,3 +113,7 @@ $(TARGET).memfile: $(TARGET) extractFunctionRadix.sh $<.objdump mkdir -p ../../imperas-riscv-tests/work/rv64BP/ cp -f $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/ + @echo 'Splitting memfile.' + ./splitfile.sh $@ + mv boot.mem ../src/boot.mem + mv data.mem ../src/data.mem diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index d333048b7..e2e76288b 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -83,11 +83,26 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE end else begin: ram bit [WIDTH-1:0] RAM[DEPTH-1:0]; - if (PRELOAD_ENABLED) begin - initial begin - RAM[0] = 64'h00600100d2e3ca40; + // if (PRELOAD_ENABLED) begin + // initial begin + // RAM[0] = 64'h00600100d2e3ca40; + // end + // end + + initial + if (PRELOAD_ENABLED) begin + if (WIDTH == 64) begin + `ifdef VERILATOR + // because Verilator doesn't automatically accept $WALLY from shell + string WALLY_DIR = getenvval("WALLY"); + $readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + `else + $readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + `endif + end else begin // put something in the ROM so it is not optimized away + RAM[0] = 'h00002197; + end end - end // Combinational read: register address and read after clock edge logic [$clog2(DEPTH)-1:0] addrd; diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index c3414352f..7de407c63 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -78,13 +78,13 @@ module uncore import cvw::*; #(parameter cvw_t P)( logic SDCIntM; logic PCLK, PRESETn, PWRITE, PENABLE; - logic [4:0] PSEL; + logic [5:0] PSEL; logic [31:0] PADDR; logic [P.XLEN-1:0] PWDATA; logic [P.XLEN/8-1:0] PSTRB; /* verilator lint_off UNDRIVEN */ // undriven in rv32e configuration - logic [4:0] PREADY; - logic [4:0][P.XLEN-1:0] PRDATA; + logic [5:0] PREADY; + logic [5:0][P.XLEN-1:0] PRDATA; /* verilator lint_on UNDRIVEN */ logic [P.XLEN-1:0] HREADBRIDGE; logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED; @@ -102,7 +102,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( // AHB -> APB bridge ahbapbbridge #(P, 6) ahbapbbridge ( - .HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO, HSELSDC}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, + .HCLK, .HRESETn, .HSEL({HSELSDC, HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE), .PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA); assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI | HSELSDC; // if any of the bridge signals are selected @@ -172,7 +172,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr)); end else begin : sdc - assign SDCCmd = '0; assign SDCCD = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; + assign SDCCmd = '0; assign SDCCS = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; end diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 3bf8f1a2e..c8e659670 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -76,8 +76,7 @@ module testbench; // DUT signals logic [P.AHBW-1:0] HRDATAEXT; - logic HREADYEXT, HRESPEXT; - logic HSELEXTSDC; + logic HREADYEXT, HRESPEXT; logic [P.PA_BITS-1:0] HADDR; logic [P.AHBW-1:0] HWDATA; logic [P.XLEN/8-1:0] HWSTRB; @@ -93,7 +92,11 @@ module testbench; logic UARTSin, UARTSout; logic SPIIn, SPIOut; logic [3:0] SPICS; - logic SDCIntr; + logic SPICLK; + logic SDCCmd; + logic SDCIn; + logic [3:0] SDCCS; + logic SDCCLK; logic HREADY; logic HSELEXT; @@ -371,6 +374,11 @@ module testbench; uartoutfile = $fopen(uartoutfilename, "w"); // delete UART output file ProgramAddrMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.addr"}; ProgramLabelMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.lab"}; + end else if(TEST == "fpga") begin + bootmemfilename = {WALLY_DIR, "/fpga/src/boot.mem"}; + memfilename = {WALLY_DIR, "/fpga/src/data.mem"}; + ProgramAddrMapFile = {WALLY_DIR, "/fpga/zsbl/bin/boot.objdump.addr"}; + ProgramLabelMapFile = {WALLY_DIR, "/fpga/zsbl/bin/boot.objdump.lab"}; end else if(ElfFile != "none") begin elffilename = ElfFile; memfilename = {ElfFile, ".memfile"}; @@ -505,6 +513,23 @@ module testbench; end readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile); $fclose(memFile); + end else if (TEST == "fpga") begin + memFile = $fopen(bootmemfilename, "rb"); + if (memFile == 0) begin + $display("Error: Could not open file %s", memfilename); + $finish; + end + if (P.BOOTROM_SUPPORTED) begin + readResult = $fread(dut.uncoregen.uncore.bootrom.bootrom.memory.ROM, memFile); + end + $fclose(memFile); + memFile = $fopen(memfilename, "rb"); + if (memFile == 0) begin + $display("Error: Could not open file %s", memfilename); + $finish; + end + readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile); + $fclose(memFile); end else begin uncoreMemFile = $fopen(memfilename, "r"); // Is there a better way to test if a file exists? if (uncoreMemFile == 0) begin @@ -584,15 +609,15 @@ module testbench; assign SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i; assign SDCDatIn = SDCDat; -----/\----- EXCLUDED -----/\----- */ - assign SDCIntr = 1'b0; end else begin - assign SDCIntr = 1'b0; + assign SDCIn = 1'b1; + end - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS); + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); // generate clock to sequence tests always begin From d5af25ffbf03b27c336468ed19e24296254aa96c Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 25 Jul 2024 09:19:23 -0700 Subject: [PATCH 144/163] CHeck legal rnum field when decoding aes64ks1i --- src/ieu/bmu/bmuctrl.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ieu/bmu/bmuctrl.sv b/src/ieu/bmu/bmuctrl.sv index d482616ef..d4a8afe23 100644 --- a/src/ieu/bmu/bmuctrl.sv +++ b/src/ieu/bmu/bmuctrl.sv @@ -238,7 +238,7 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) ( if ((P.ZKND_SUPPORTED | P.ZKNE_SUPPORTED) & P.XLEN == 64) begin // ZKND and ZKNE shared instructions casez({OpD, Funct7D, Funct3D}) - 17'b0010011_0011000_001: if (Rs2D[4] == 1'b1) + 17'b0010011_0011000_001: if (Rs2D[4] == 1'b1 & $unsigned(Rs2D[3:0]) <= 10) BMUControlsD = `BMUCTRLW'b000_0111_0010_1_0_0_0_1_0_0_0_0_0; // aes64ks1i - key schedule istr1 17'b0110011_0111111_000: BMUControlsD = `BMUCTRLW'b000_0111_0011_1_0_0_0_1_0_0_0_0_0; // aes64ks2 - key schedule istr2 endcase From faa13789201fa202e5b83d26e857c2f0de1b6210 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 25 Jul 2024 09:43:54 -0700 Subject: [PATCH 145/163] Legalized PMPconfig WARL --- src/privileged/csrm.sv | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index f86b3f6d6..24132ab93 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -106,7 +106,10 @@ module csrm import cvw::*; #(parameter cvw_t P) ( genvar i; if (P.PMP_ENTRIES > 0) begin:pmp logic [P.PMP_ENTRIES-1:0] WritePMPCFGM; - logic [P.PMP_ENTRIES-1:0] WritePMPADDRM ; + logic [P.PMP_ENTRIES-1:0] WritePMPADDRM; + logic [7:0] CSRPMPWriteValM[P.PMP_ENTRIES-1:0]; + logic [7:0] CSRPMPLegalizedWriteValM[P.PMP_ENTRIES-1:0]; + logic [1:0] CSRPMPWRLegalizedWriteValM[P.PMP_ENTRIES-1:0]; logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; for(i=0; i<P.PMP_ENTRIES; i++) begin // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR @@ -121,11 +124,15 @@ module csrm import cvw::*; #(parameter cvw_t P) ( flopenr #(P.PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[P.PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]); if (P.XLEN==64) begin assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i]; - flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); + assign CSRPMPWriteValM[i] = CSRWriteValM[(i%8)*8+7:(i%8)*8]; end else begin assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~CFGLocked[i]; - flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); + assign CSRPMPWriteValM[i] = CSRWriteValM[(i%4)*8+7:(i%4)*8]; end + + assign CSRPMPWRLegalizedWriteValM[i] = {(CSRPMPWriteValM[i][1] & CSRPMPWriteValM[i][0]), CSRPMPWriteValM[i][0]}; // legalize WR fields (reserved 10 written as 00) + assign CSRPMPLegalizedWriteValM[i] = {CSRPMPWriteValM[i][7], 2'b00, CSRPMPWriteValM[i][4:2], CSRPMPWRLegalizedWriteValM[i]}; + flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRPMPWriteValM[i], PMPCFG_ARRAY_REGW[i]); end end From da853b45e6beba0cb162d622a45516db764f4499 Mon Sep 17 00:00:00 2001 From: David Harris <David_Harris@hmc.edu> Date: Thu, 25 Jul 2024 10:08:34 -0700 Subject: [PATCH 146/163] Updated ImperasTG derived config to turn off peripherals --- config/derivlist.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/config/derivlist.txt b/config/derivlist.txt index 1edd20b7b..c689d2cb9 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -1657,7 +1657,7 @@ IDIV_ON_FPU 1 # imperas used for a smart memory # VCS doesn't like removing the bootrom, but make it tiny in a random unused location -derive imperas rv64gc +derive ImperasTG rv64gc ICACHE_SUPPORTED 0 DCACHE_SUPPORTED 0 VIRTMEM_SUPPORTED 0 @@ -1668,6 +1668,13 @@ ZICBOM_SUPPORTED 0 ZICBOZ_SUPPORTED 0 SVPBMT_SUPPORTED 0 SVNAPOT_SUPPORTED 0 -BOOTROM_BASE 64'h700012340010 +BOOTROM_BASE 64'h700012340080 BOOTROM_RANGE 64'h10 +CLINT_SUPPORTED 0 +GPIO_SUPPORTED 0 +UART_SUPPORTED 0 +PLIC_SUPPORTED 0 +SPI_SUPPORTED 0 + + From a36e846b0251f533ba2988da6ca2d95ce17b6e17 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Thu, 25 Jul 2024 13:04:27 -0500 Subject: [PATCH 147/163] Changed formatting and added new UART divsor calculation from OpenSBI. --- fpga/zsbl/uart.c | 91 ++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index 7ff40e516..1330bc1d9 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -3,94 +3,93 @@ void write_reg_u8(uintptr_t addr, uint8_t value) { - volatile uint8_t *loc_addr = (volatile uint8_t *)addr; - *loc_addr = value; + volatile uint8_t *loc_addr = (volatile uint8_t *)addr; + *loc_addr = value; } uint8_t read_reg_u8(uintptr_t addr) { - return *(volatile uint8_t *)addr; + return *(volatile uint8_t *)addr; } int is_transmit_empty() { - return read_reg_u8(UART_LSR) & 0x20; + return read_reg_u8(UART_LSR) & 0x20; } int is_receive_empty() { - return !(read_reg_u8(UART_LSR) & 0x1); + return !(read_reg_u8(UART_LSR) & 0x1); } void write_serial(char a) { - while (is_transmit_empty() == 0) {}; + while (is_transmit_empty() == 0) {}; - write_reg_u8(UART_THR, a); + write_reg_u8(UART_THR, a); } void init_uart(uint32_t freq, uint32_t baud) { - uint32_t divisor = freq / (baud << 4); + // Alternative divisor calculation. From OpenSBI code. + // Reduces error for every possible frequency. + uint32_t divisor = (freq + 8 * baud) /(baud << 4); - write_reg_u8(UART_IER, 0x00); // Disable all interrupts - write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) - write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte) - write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) - write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit - write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + write_reg_u8(UART_IER, 0x00); // Disable all interrupts + write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) + write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte) + write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) + write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit + write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold } void print_uart(const char *str) { - const char *cur = &str[0]; - while (*cur != '\0') - { - write_serial((uint8_t)*cur); - ++cur; - } + const char *cur = &str[0]; + while (*cur != '\0') { + write_serial((uint8_t)*cur); + ++cur; + } } uint8_t bin_to_hex_table[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; void bin_to_hex(uint8_t inp, uint8_t res[2]) { - res[1] = bin_to_hex_table[inp & 0xf]; - res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; - return; + res[1] = bin_to_hex_table[inp & 0xf]; + res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; + return; } void print_uart_int(uint32_t addr) { - int i; - for (i = 3; i > -1; i--) - { - uint8_t cur = (addr >> (i * 8)) & 0xff; - uint8_t hex[2]; - bin_to_hex(cur, hex); - write_serial(hex[0]); - write_serial(hex[1]); - } + int i; + for (i = 3; i > -1; i--) { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } } void print_uart_addr(uint64_t addr) { - int i; - for (i = 7; i > -1; i--) - { - uint8_t cur = (addr >> (i * 8)) & 0xff; - uint8_t hex[2]; - bin_to_hex(cur, hex); - write_serial(hex[0]); - write_serial(hex[1]); - } + int i; + for (i = 7; i > -1; i--) { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } } void print_uart_byte(uint8_t byte) { - uint8_t hex[2]; - bin_to_hex(byte, hex); - write_serial(hex[0]); - write_serial(hex[1]); + uint8_t hex[2]; + bin_to_hex(byte, hex); + write_serial(hex[0]); + write_serial(hex[1]); } From 3975f60299c18bfb4f5fce2be64d552f3752c3d2 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Thu, 25 Jul 2024 13:05:57 -0500 Subject: [PATCH 148/163] Added carriage returns to line feed characters. UART messages print properly now. --- fpga/zsbl/boot.c | 5 ++++- fpga/zsbl/boot.h | 18 +++++++++--------- fpga/zsbl/gpt.c | 6 +++--- fpga/zsbl/sd.c | 4 ++-- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index e8065f732..5b022cea3 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -49,6 +49,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { if (sd_cmd(18, sector & 0xffffffff, crc) != 0x00) { print_uart("disk_read: CMD18 failed. r = "); print_uart_byte(r & 0xff); + print_uart("\r\n"); return -1; } @@ -61,6 +62,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { if (r != SD_DATA_TOKEN) { print_uart("Didn't receive data token first thing. Shoot: "); print_uart_byte(r & 0xff); + print_uart("\r\n"); return -1; } @@ -97,7 +99,8 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Initialize UART for messages init_uart(20000000, 115200); - + + print_uart("Booting wally.\r\n"); // Print the wally banner print_uart(BANNER); diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 2048ca47c..087550326 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -19,15 +19,15 @@ typedef QWORD LBA_t; #define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START #define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR -#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\n" \ -" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\n" \ -" █▄█ █▄█ █ █ █▄▄ ▀▄▀\n" \ -" ____ ____ ____ ___ ___ ____ ___\n" \ -" \\ \\ / / / \\ | | | | \\ \\ / /\n" \ -" \\ \\ __ / / / \\ | | | | \\ \\/ /\n" \ -" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\n" \ -" \\ / / ____ \\ | |___ | |___ | |\n" \ -" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" +#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\r\n" \ +" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\r\n" \ +" █▄█ █▄█ █ █ █▄▄ ▀▄▀\r\n" \ +" ____ ____ ____ ___ ___ ____ ___\r\n" \ +" \\ \\ / / / \\ | | | | \\ \\ / /\r\n" \ +" \\ \\ __ / / / \\ | | | | \\ \\/ /\r\n" \ +" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\r\n" \ +" \\ / / ____ \\ | |___ | |___ | |\r\n" \ +" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\r\n\r\n" // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count); diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index c308ea878..a52dc9048 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -42,21 +42,21 @@ int gpt_load_partitions() { // Load device tree ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); if (ret < 0) { - print_uart("Failed to load device tree!"); + print_uart("Failed to load device tree!\r\n"); return -1; } // Load OpenSBI ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); if (ret < 0) { - print_uart("Failed to load OpenSBI!"); + print_uart("Failed to load OpenSBI!\r\n"); return -1; } // Load Linux ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); if (ret < 0) { - print_uart("Failed to load Linux!"); + print_uart("Failed to load Linux!\r\n"); return -1; } diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 585b98281..02ee4d3bf 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -133,7 +133,7 @@ void init_sd(){ uint64_t r; - print_uart("Initializing SD Card in SPI mode"); + print_uart("Initializing SD Card in SPI mode.\r\n"); // Reset SD Card command // Initializes SD card into SPI mode if CS is asserted '0' @@ -155,6 +155,6 @@ void init_sd(){ r = ACMD41(); } while (r == 0x1); - print_uart("SD card is initialized"); + print_uart("SD card is initialized.\n\r"); } From a263f836f2d322c0f4a5db4e1303e282e741c31b Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 31 Jul 2024 10:58:15 -0500 Subject: [PATCH 149/163] Added extra UART macros and functions for code readability and the ability to print decimal numbers. --- fpga/zsbl/uart.c | 68 +++++++++++++++++++++++++++++++++++------------- fpga/zsbl/uart.h | 20 +++++++++++++- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index 1330bc1d9..d7ac9b558 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -62,10 +62,10 @@ void bin_to_hex(uint8_t inp, uint8_t res[2]) return; } -void print_uart_int(uint32_t addr) +void print_uart_hex(uint64_t addr, int n) { int i; - for (i = 3; i > -1; i--) { + for (i = n - 1; i > -1; i--) { uint8_t cur = (addr >> (i * 8)) & 0xff; uint8_t hex[2]; bin_to_hex(cur, hex); @@ -74,22 +74,54 @@ void print_uart_int(uint32_t addr) } } -void print_uart_addr(uint64_t addr) -{ - int i; - for (i = 7; i > -1; i--) { - uint8_t cur = (addr >> (i * 8)) & 0xff; - uint8_t hex[2]; - bin_to_hex(cur, hex); - write_serial(hex[0]); - write_serial(hex[1]); +void print_uart_dec(uint64_t addr) { + + // floor(log(2^64)) = 19 + char str[19] = {'\0'}; + uint8_t length = 0; + + uint64_t cur = addr; + while (cur != 0) { + char digit = bin_to_hex_table[cur % 10]; + // write_serial(digit); + str[length] = digit; + cur = cur/10; + length++; + } + + for (int i = length; i > -1; i--) { + write_serial(str[i]); } } -void print_uart_byte(uint8_t byte) -{ - uint8_t hex[2]; - bin_to_hex(byte, hex); - write_serial(hex[0]); - write_serial(hex[1]); -} +/* void print_uart_int(uint32_t addr) */ +/* { */ +/* int i; */ +/* for (i = 3; i > -1; i--) { */ +/* uint8_t cur = (addr >> (i * 8)) & 0xff; */ +/* uint8_t hex[2]; */ +/* bin_to_hex(cur, hex); */ +/* write_serial(hex[0]); */ +/* write_serial(hex[1]); */ +/* } */ +/* } */ + +/* void print_uart_addr(uint64_t addr) */ +/* { */ +/* int i; */ +/* for (i = 7; i > -1; i--) { */ +/* uint8_t cur = (addr >> (i * 8)) & 0xff; */ +/* uint8_t hex[2]; */ +/* bin_to_hex(cur, hex); */ +/* write_serial(hex[0]); */ +/* write_serial(hex[1]); */ +/* } */ +/* } */ + +/* void print_uart_byte(uint8_t byte) */ +/* { */ +/* uint8_t hex[2]; */ +/* bin_to_hex(byte, hex); */ +/* write_serial(hex[0]); */ +/* write_serial(hex[1]); */ +/* } */ diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index 18710e76b..ee399885f 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -16,11 +16,29 @@ #define UART_DLL UART_BASE + 0x00 #define UART_DLM UART_BASE + 0x01 -void init_uart(); +void init_uart(uint32_t freq, uint32_t baud); void write_reg_u8(uintptr_t addr, uint8_t value); uint8_t read_reg_u8(uintptr_t addr); int read_serial(uint8_t *res); void print_uart(const char* str); void print_uart_int(uint32_t addr); +void print_uart_dec(uint64_t addr); void print_uart_addr(uint64_t addr); +void print_uart_hex(uint64_t addr, int n); void print_uart_byte(uint8_t byte); + +#define print_uart_int(addr) print_uart_hex(addr, 4) +#define print_uart_addr(addr) print_uart_hex(addr, 8) +#define print_uart_byte(addr) print_uart_hex(addr, 1) +#define print_r7(addr) print_uart_hex(addr, 5) +#define print_r1(addr) print_uart_byte(addr) + +// Print line with numbers utility macros +#define println(msg) print_uart(msg "\r\n"); +#define println_with_dec(msg, num) print_uart(msg); print_uart_dec(num); print_uart("\r\n") +#define println_with_byte(msg, num) print_uart(msg); print_uart_byte(num); print_uart("\r\n") +#define println_with_int(msg, num) print_uart(msg); print_uart_int(num); print_uart("\r\n") +#define println_with_addr(msg, num) print_uart(msg); print_uart_addr(num); print_uart("\r\n") +#define println_with_r1(msg, num) print_uart(msg); print_r1(num); print_uart("\r\n") +#define println_with_r7(msg, num) print_uart(msg); print_r7(num); print_uart("\r\n") + From c4ae17c6797ecdb734be059df83634e70922d2ad Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 31 Jul 2024 10:59:41 -0500 Subject: [PATCH 150/163] Cleaned up code formatting a bit and added ability to set the SD card clock speed. --- fpga/zsbl/sd.c | 65 ++++++++++++++++++++++++++++++++++++++------------ fpga/zsbl/sd.h | 4 ++-- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 02ee4d3bf..cacf40438 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -62,8 +62,14 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // response length. Probably unecessary so let's wait and see what // happens. // write_reg(SPI_RXMARK, response_len); + + // Chip select must remain asserted during transaction + if (cmd != SD_CMD_STOP_TRANSMISSION) { + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); + } - // Write all 6 bytes into transfer fifo + // Write all 7 bytes into transfer fifo + // spi_sendbyte(0xff); spi_sendbyte(0x40 | cmd); spi_sendbyte(arg >> 24); spi_sendbyte(arg >> 16); @@ -77,7 +83,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { waittx(); // Read the dummy rxFIFO entries to move the head back to the tail - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { spi_readbyte(); } @@ -90,12 +96,24 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // Wait for transfer fifo again waittx(); + // Wait for actual response from SD card + // All responses start with a 0. Output of SDCIn is high, unless + // a message is being transferred. + do { + rbyte = spi_txrx(0xff); + } while ( (rbyte & 0x80) != 0 ); + + r = r | (rbyte << ((response_len - 1)*8)); + // Read rxfifo response - for (i = 0; i < response_len; i++) { + for (i = 1; i < response_len; i++) { rbyte = spi_readbyte(); r = r | (rbyte << ((response_len - 1 - i)*8)); } + if (cmd != 18) { + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + } return r; } // sd_cmd @@ -128,33 +146,50 @@ uint64_t sd_read64(uint16_t * crc) { // init_sd: ---------------------------------------------------------- // This first initializes the SPI peripheral then initializes the SD // card itself. We use the uart to display anything that goes wrong. -void init_sd(){ +int init_sd(uint32_t freq, uint32_t sdclk){ spi_init(); uint64_t r; + uint32_t newClockDiv; - print_uart("Initializing SD Card in SPI mode.\r\n"); + println("Initializing SD Card in SPI mode."); + // This is necessary. This is the card's pre-init state initialization. + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_OFF); + for (int i = 0; i < 10; i++) { + spi_txrx(0xff); + } + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + // CMD0 -------------------------------------------------------------- // Reset SD Card command // Initializes SD card into SPI mode if CS is asserted '0' - if (!(( r = CMD0() ) & 0x10) ) { - print_uart("SD ERROR: "); - print_uart_byte(r & 0xff); - print_uart("\r\n"); - } + // We expect to get the R1 response 0x01 which means that the + // card has been put into the idle state. + print_uart("CMD0: "); + do { + r = CMD0(); + } while ( r != 0x01 ); + println_with_r1("Success, r = 0x", r & 0xff); + // CMD8 ------------------------------------------------------------- // - if (!(( r = CMD8() ) & 0x10 )) { - print_uart("SD ERROR: "); - print_uart_byte(r & 0xff); - print_uart("\r\n"); + print_uart("CMD8: "); + r = CMD8(); + if ((r & 0x000000ff0000ffff) != 0x01000001aa) { + println_with_r7("Failed, 0x", r); } + println_with_r7("Success, 0x", r); + // ACMD41 ----------------------------------------------------------- + print_uart("ACMD41: "); do { CMD55(); r = ACMD41(); } while (r == 0x1); + println_with_r1("Success, r = 0x", r & 0xff); - print_uart("SD card is initialized.\n\r"); + println_with_dec("New clock frequency: ", (uint64_t)sdclk); + spi_set_clock(freq, sdclk); + println("SD card is initialized."); } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index 37e4a2c94..f695b83e5 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -9,11 +9,11 @@ // Response lengths in bytes #define R1_RESPONSE 1 -#define R7_RESPONSE 7 +#define R7_RESPONSE 5 #define R1B_RESPONSE 2 uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); uint64_t sd_read64(uint16_t * crc); -void init_sd(); +int init_sd(uint32_t freq, uint32_t sdclk); From ee980e39f306cebc9eb2ce7af2c3a0acd8352d91 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 31 Jul 2024 11:00:44 -0500 Subject: [PATCH 151/163] Added function to set SPI clock speed. --- fpga/zsbl/spi.c | 7 ++++++- fpga/zsbl/spi.h | 5 +---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index cbb9fa2eb..b8829b12e 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -83,8 +83,13 @@ uint64_t spi_read64() { return r; } +void spi_set_clock(uint32_t clkin, uint32_t clkout) { + uint32_t div = (clkin/(2*clkout)) - 1; + write_reg(SPI_SCKDIV, div); +} + // Initialize Sifive FU540 based SPI Controller -void spi_init() { +void spi_init(uint32_t clkin) { // Enable interrupts write_reg(SPI_IE, 0x3); diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index bc85c768f..a662fce86 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -44,10 +44,6 @@ #define SIFIVE_SPI_CSMODE_MODE_HOLD 2U #define SIFIVE_SPI_CSMODE_MODE_OFF 3U - -#define WAITTX while(!(read_reg(SPI_IP) & 1) {} -#define WAITRX while(read_reg(SPI_IP) & 2) {} - // inline void write_reg(uintptr_t addr, uint32_t value); //inline uint32_t read_reg(uintptr_t addr); //inline void spi_sendbyte(uint8_t byte); @@ -57,6 +53,7 @@ uint8_t spi_txrx(uint8_t byte); //inline uint8_t spi_readbyte(); uint64_t spi_read64(); void spi_init(); +void spi_set_clock(uint32_t clkin, uint32_t clkout); static inline void write_reg(uintptr_t addr, uint32_t value) { volatile uint32_t * loc = (volatile uint32_t *) addr; From 38071d826736f527820b94d8492492898171bf3e Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Wed, 31 Jul 2024 11:12:05 -0500 Subject: [PATCH 152/163] Updated formatting of gpt.c and boot.c. --- fpga/zsbl/boot.c | 40 ++++++++++++++++++++++++++-------------- fpga/zsbl/gpt.c | 21 +++++---------------- fpga/zsbl/uart.h | 3 +++ 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 5b022cea3..7b2e9af7d 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -34,10 +34,12 @@ /* return 0;; */ /* } */ +#define SYSTEMCLOCK 20000000 + int disk_read(BYTE * buf, LBA_t sector, UINT count) { uint64_t r; UINT i; - + uint8_t crc = 0; crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE); crc = crc7(crc, (sector >> 24) & 0xff); @@ -46,25 +48,29 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { crc = crc7(crc, sector & 0xff); crc = crc | 1; - if (sd_cmd(18, sector & 0xffffffff, crc) != 0x00) { - print_uart("disk_read: CMD18 failed. r = "); - print_uart_byte(r & 0xff); + if ((r = sd_cmd(18, sector & 0xffffffff, crc) & 0xff) != 0x00) { + print_uart("disk_read: CMD18 failed. r = 0x"); + print_uart_byte(r); print_uart("\r\n"); return -1; } + // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); // Begin reading blocks for (i = 0; i < count; i++) { uint16_t crc, crc_exp; // Read the data token r = spi_readbyte(); - if (r != SD_DATA_TOKEN) { - print_uart("Didn't receive data token first thing. Shoot: "); - print_uart_byte(r & 0xff); - print_uart("\r\n"); - return -1; - } + /* if (r != SD_DATA_TOKEN) { */ + /* print_uart("Didn't receive data token first thing. Shoot: "); */ + /* print_uart_byte(r & 0xff); */ + /* print_uart("\r\n"); */ + /* return -1; */ + /* } */ + + // Wait for data token + while((r & 0xff) != SD_DATA_TOKEN); // Read block into memory. for (int j = 0; j < 8; j++) { @@ -77,7 +83,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { crc_exp |= spi_txrx(0xff); if (crc != crc_exp) { - print_uart("Stinking CRC16 didn't match on block "); + print_uart("Stinking CRC16 didn't match on block read.\r\n"); print_uart_int(i); print_uart("\r\n"); return -1; @@ -86,7 +92,8 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { } sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01); - spi_txrx(0xff); + // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + //spi_txrx(0xff); return 0; } @@ -100,12 +107,17 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Initialize UART for messages init_uart(20000000, 115200); - print_uart("Booting wally.\r\n"); // Print the wally banner print_uart(BANNER); + /* print_uart("System clock speed: "); */ + /* print_uart_dec(SYSTEMCLOCK); */ + /* print_uart("\r\n"); */ + + println_with_dec("Hello, does this work? Here's the clock: ", SYSTEMCLOCK); + // Intialize the SD card - init_sd(); + init_sd(SYSTEMCLOCK, SYSTEMCLOCK/2); ret = gpt_load_partitions(); } diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index a52dc9048..9af396469 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -3,18 +3,7 @@ #include "uart.h" #include <stddef.h> -/* PSUEDOCODE - - Need to load GPT LBA 1 and read through the partition entries. - I need to find each of the relevant partition entries, possibly - by their partition names. - -*/ - int gpt_load_partitions() { - // In this version of the GPT partition code - // I'm going to assume that the SD card is already initialized. - // size_t block_size = 512/8; // long int lba1_buf[block_size]; @@ -22,15 +11,12 @@ int gpt_load_partitions() { int ret = 0; //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */); + println("Getting GPT information."); ret = disk_read(lba1_buf, 1, 1); - /* Possible error handling with UART message - if ( ret != 0 ) { - - }*/ - gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; + println("Getting partition entries."); BYTE lba2_buf[512]; ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1); @@ -40,6 +26,7 @@ int gpt_load_partitions() { partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); // Load device tree + println_with_int("Loading device tree at: 0x", FDT_ADDRESS); ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); if (ret < 0) { print_uart("Failed to load device tree!\r\n"); @@ -47,6 +34,7 @@ int gpt_load_partitions() { } // Load OpenSBI + println_with_int("Loading OpenSBI at: 0x", OPENSBI_ADDRESS); ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); if (ret < 0) { print_uart("Failed to load OpenSBI!\r\n"); @@ -54,6 +42,7 @@ int gpt_load_partitions() { } // Load Linux + println_with_int("Loading Linux Kernel at: 0x", KERNEL_ADDRESS); ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); if (ret < 0) { print_uart("Failed to load Linux!\r\n"); diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index ee399885f..515a9dccd 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -1,6 +1,7 @@ #pragma once #include <stdint.h> +// UART register addresses #define UART_BASE 0x10000000 #define UART_RBR UART_BASE + 0x00 @@ -16,6 +17,7 @@ #define UART_DLL UART_BASE + 0x00 #define UART_DLM UART_BASE + 0x01 +// Primary function prototypes void init_uart(uint32_t freq, uint32_t baud); void write_reg_u8(uintptr_t addr, uint8_t value); uint8_t read_reg_u8(uintptr_t addr); @@ -27,6 +29,7 @@ void print_uart_addr(uint64_t addr); void print_uart_hex(uint64_t addr, int n); void print_uart_byte(uint8_t byte); +// Print numbers in hex with specified widths #define print_uart_int(addr) print_uart_hex(addr, 4) #define print_uart_addr(addr) print_uart_hex(addr, 8) #define print_uart_byte(addr) print_uart_hex(addr, 1) From fcd88d6e6f4c0a1adc334f2d84eb2a8c82e93ee7 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 2 Aug 2024 15:14:30 -0500 Subject: [PATCH 153/163] Added functions to read registers and print information on failure. Also added a getTime function for a pretty boot display. --- fpga/zsbl/fail.c | 19 +++++++++++++++++++ fpga/zsbl/fail.h | 4 ++++ fpga/zsbl/riscv.S | 29 +++++++++++++++++++++++++++++ fpga/zsbl/riscv.h | 7 +++++++ fpga/zsbl/time.c | 20 ++++++++++++++++++++ fpga/zsbl/time.h | 5 +++++ 6 files changed, 84 insertions(+) create mode 100644 fpga/zsbl/fail.c create mode 100644 fpga/zsbl/fail.h create mode 100644 fpga/zsbl/riscv.S create mode 100644 fpga/zsbl/riscv.h create mode 100644 fpga/zsbl/time.c create mode 100644 fpga/zsbl/time.h diff --git a/fpga/zsbl/fail.c b/fpga/zsbl/fail.c new file mode 100644 index 000000000..4e6cd8db0 --- /dev/null +++ b/fpga/zsbl/fail.c @@ -0,0 +1,19 @@ +#include "fail.h" +#include "uart.h" +#include "riscv.h" +#include "time.h" + +void fail() { + // Get address that led to failure + register uint64_t addr; + asm volatile ("mv %0, ra" : "=r"(addr) : : "memory"); + + // Print message + print_time(); + println_with_addr("Failed at: 0x", addr); + + // Loop forever + while(1) { + + } +} diff --git a/fpga/zsbl/fail.h b/fpga/zsbl/fail.h new file mode 100644 index 000000000..da1a2e405 --- /dev/null +++ b/fpga/zsbl/fail.h @@ -0,0 +1,4 @@ +#pragma once +#include <stdint.h> + +void fail(); diff --git a/fpga/zsbl/riscv.S b/fpga/zsbl/riscv.S new file mode 100644 index 000000000..7f400b1b2 --- /dev/null +++ b/fpga/zsbl/riscv.S @@ -0,0 +1,29 @@ +.section .text +.globl read_mcycle +.type read_mcycle, @function +read_mcycle: + csrr a0, mcycle + ret + +.section .text +.globl get_ra +.type get_ra, @function +get_ra: + mv a0, ra + ret + +.section .text +.globl set_status_fs +.type set_status_fs, @function +set_status_fs: + lui t1, 0x6 + csrs mstatus, t1 + ret + +.section .text +.globl clear_status_fs +.type clear_status_fs, @function +clear_status_fs: + lui t1, 0x6 + csrc mstatus, t1 + ret diff --git a/fpga/zsbl/riscv.h b/fpga/zsbl/riscv.h new file mode 100644 index 000000000..a27cd48d6 --- /dev/null +++ b/fpga/zsbl/riscv.h @@ -0,0 +1,7 @@ +#pragma once +#include <stdint.h> + +uint64_t read_mcycle(); +uint64_t get_ra(); +void set_status_fs(); +void clear_status_fs(); diff --git a/fpga/zsbl/time.c b/fpga/zsbl/time.c new file mode 100644 index 000000000..43ac085b7 --- /dev/null +++ b/fpga/zsbl/time.c @@ -0,0 +1,20 @@ +#include "time.h" +#include "boot.h" +#include "riscv.h" +#include "uart.h" + +float getTime() { + set_status_fs(); + float numCycles = (float)read_mcycle(); + float ret = numCycles/SYSTEMCLOCK; + // clear_status_fs(); + return ret; +} + +void print_time() { + print_uart("["); + set_status_fs(); + print_uart_float(getTime(),5); + clear_status_fs(); + print_uart("] "); +} diff --git a/fpga/zsbl/time.h b/fpga/zsbl/time.h new file mode 100644 index 000000000..6cd928b88 --- /dev/null +++ b/fpga/zsbl/time.h @@ -0,0 +1,5 @@ +#pragma once +#include <stdint.h> + +float getTime(); +void print_time(); From 897f6561cd53fa3875ddd4a14bc4697369f562c7 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 2 Aug 2024 15:19:52 -0500 Subject: [PATCH 154/163] New bootloader now works. Added special print functions and print messages. sdclk is set to 3MHz after initialization currently. --- fpga/zsbl/boot.c | 92 +++++++++++++++++++++++++++++++++++------------- fpga/zsbl/boot.h | 2 ++ fpga/zsbl/gpt.c | 8 +++++ fpga/zsbl/sd.c | 63 ++++++++++++++++++++++++--------- fpga/zsbl/spi.c | 6 +++- fpga/zsbl/spi.h | 1 + fpga/zsbl/uart.c | 40 +++++++++++++++++++-- fpga/zsbl/uart.h | 11 ++++++ 8 files changed, 179 insertions(+), 44 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 7b2e9af7d..e47b34e2f 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -4,6 +4,9 @@ #include "uart.h" #include "spi.h" #include "sd.h" +#include "time.h" +#include "riscv.h" +#include "fail.h" /* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ @@ -34,11 +37,31 @@ /* return 0;; */ /* } */ -#define SYSTEMCLOCK 20000000 +// Need to convert this +/* void print_progress(size_t count, size_t max) { */ +/* const int bar_width = 50; */ + +/* float progress = (float) count / max; */ +/* int bar_length = progress * bar_width; */ + +/* printf("\r["); */ +/* for (int i = 0; i < bar_length; ++i) { */ +/* printf("#"); */ +/* } */ +/* for (int i = bar_length; i < bar_width; ++i) { */ +/* printf("-"); */ +/* } */ +/* printf("] %.2f%%", progress * 100); */ + +/* fflush(stdout); */ +/* } */ int disk_read(BYTE * buf, LBA_t sector, UINT count) { uint64_t r; UINT i; + volatile uint8_t *p = buf; + + UINT modulus = count/50; uint8_t crc = 0; crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE); @@ -52,48 +75,69 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { print_uart("disk_read: CMD18 failed. r = 0x"); print_uart_byte(r); print_uart("\r\n"); - return -1; + fail(); + // return -1; } + print_uart("\r Blocks loaded: "); + print_uart("0"); + print_uart("/"); + print_uart_dec(count); // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); // Begin reading blocks for (i = 0; i < count; i++) { uint16_t crc, crc_exp; - - // Read the data token - r = spi_readbyte(); - /* if (r != SD_DATA_TOKEN) { */ - /* print_uart("Didn't receive data token first thing. Shoot: "); */ - /* print_uart_byte(r & 0xff); */ - /* print_uart("\r\n"); */ - /* return -1; */ - /* } */ + uint64_t n = 0; // Wait for data token - while((r & 0xff) != SD_DATA_TOKEN); + while((r = spi_dummy()) != SD_DATA_TOKEN); + // println_with_byte("Received data token: 0x", r & 0xff); + // println_with_dec("Block ", i); // Read block into memory. - for (int j = 0; j < 8; j++) { - *buf = sd_read64(&crc); - buf = buf + 64; - } - + /* for (int j = 0; j < 64; j++) { */ + /* *buf = sd_read64(&crc); */ + /* println_with_addr("0x", *buf); */ + /* buf = buf + 64; */ + /* } */ + crc = 0; + n = 512; + do { + uint8_t x = spi_dummy(); + *p++ = x; + crc = crc16(crc, x); + } while (--n > 0); + // Read CRC16 and check - crc_exp = ((uint16_t)spi_txrx(0xff) << 8); - crc_exp |= spi_txrx(0xff); + crc_exp = ((uint16_t)spi_dummy() << 8); + crc_exp |= spi_dummy(); if (crc != crc_exp) { print_uart("Stinking CRC16 didn't match on block read.\r\n"); print_uart_int(i); print_uart("\r\n"); - return -1; + //return -1; + fail(); } - + + if ( (i % modulus) == 0 ) { + print_uart("\r Blocks loaded: "); + print_uart_dec(i); + print_uart("/"); + print_uart_dec(count); + } + } sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01); + + print_uart("\r Blocks loaded: "); + print_uart_dec(count); + print_uart("/"); + print_uart_dec(count); // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); //spi_txrx(0xff); + print_uart("\r\n"); return 0; } @@ -106,7 +150,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Initialize UART for messages init_uart(20000000, 115200); - + // Print the wally banner print_uart(BANNER); @@ -114,10 +158,8 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { /* print_uart_dec(SYSTEMCLOCK); */ /* print_uart("\r\n"); */ - println_with_dec("Hello, does this work? Here's the clock: ", SYSTEMCLOCK); - // Intialize the SD card - init_sd(SYSTEMCLOCK, SYSTEMCLOCK/2); + init_sd(SYSTEMCLOCK, 3000000); ret = gpt_load_partitions(); } diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 087550326..25b8a5fcc 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -32,5 +32,7 @@ typedef QWORD LBA_t; // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count); +#define SYSTEMCLOCK 20000000 + #endif // WALLYBOOT diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 9af396469..99f74ec3a 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -11,11 +11,13 @@ int gpt_load_partitions() { int ret = 0; //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */); + print_time(); println("Getting GPT information."); ret = disk_read(lba1_buf, 1, 1); gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; + print_time(); println("Getting partition entries."); BYTE lba2_buf[512]; ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1); @@ -26,6 +28,7 @@ int gpt_load_partitions() { partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); // Load device tree + print_time(); println_with_int("Loading device tree at: 0x", FDT_ADDRESS); ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); if (ret < 0) { @@ -34,6 +37,7 @@ int gpt_load_partitions() { } // Load OpenSBI + print_time(); println_with_int("Loading OpenSBI at: 0x", OPENSBI_ADDRESS); ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); if (ret < 0) { @@ -42,6 +46,7 @@ int gpt_load_partitions() { } // Load Linux + print_time(); println_with_int("Loading Linux Kernel at: 0x", KERNEL_ADDRESS); ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); if (ret < 0) { @@ -49,5 +54,8 @@ int gpt_load_partitions() { return -1; } + print_time(); + println("Done! Flashing LEDs and jumping to OpenSBI..."); + return 0; } diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index cacf40438..484fd65c0 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,6 +1,8 @@ #include "sd.h" #include "spi.h" #include "uart.h" +#include "fail.h" +#include "time.h" // Parallel byte update CRC7-CCITT algorithm. // The result is the CRC7 result, left shifted over by 1 @@ -36,9 +38,11 @@ uint16_t crc16(uint16_t crc, uint8_t data) { // watermark and interrupt features to determine when a // transfer is complete. This should save on cycles since // no arbitrary delays need to be added. + uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t response_len; uint8_t i; + uint8_t shiftAmnt; uint64_t r; uint8_t rbyte; @@ -53,6 +57,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { break; case 12: response_len = R1B_RESPONSE; + break; default: response_len = R1_RESPONSE; break; @@ -70,6 +75,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // Write all 7 bytes into transfer fifo // spi_sendbyte(0xff); + spi_dummy(); spi_sendbyte(0x40 | cmd); spi_sendbyte(arg >> 24); spi_sendbyte(arg >> 16); @@ -89,30 +95,34 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // Send "dummy signals". Since SPI is duplex, // useless bytes must be transferred - for (i = 0; i < response_len; i++) { - spi_sendbyte(0xFF); - } + /* for (i = 0; i < response_len; i++) { */ + /* spi_sendbyte(0xFF); */ + /* } */ - // Wait for transfer fifo again - waittx(); + /* // Wait for transfer fifo again */ + /* waittx(); */ // Wait for actual response from SD card // All responses start with a 0. Output of SDCIn is high, unless // a message is being transferred. do { - rbyte = spi_txrx(0xff); + rbyte = spi_dummy(); } while ( (rbyte & 0x80) != 0 ); - r = r | (rbyte << ((response_len - 1)*8)); + // Note about the compiler. In order to compile as sll instead of + // sllw, the number to shift has to be a 64 bit number. + r = ((uint64_t)rbyte) << ((response_len - 1)*8); // Read rxfifo response for (i = 1; i < response_len; i++) { - rbyte = spi_readbyte(); - r = r | (rbyte << ((response_len - 1 - i)*8)); + rbyte = spi_dummy(); + r = r | (((uint64_t)rbyte) << ((response_len - 1 - i)*8)); } if (cmd != 18) { write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + } else { + spi_dummy(); } return r; } // sd_cmd @@ -122,16 +132,16 @@ uint64_t sd_read64(uint16_t * crc) { uint8_t rbyte; int i; - for (i = 0; i < 8; i++) { - spi_sendbyte(0xFF); - } + /* for (i = 0; i < 8; i++) { */ + /* spi_sendbyte(0xFF); */ + /* } */ - waittx(); + /* waittx(); */ for (i = 0; i < 8; i++) { - rbyte = spi_readbyte(); + rbyte = spi_dummy(); *crc = crc16(*crc, rbyte); - r = r | (rbyte << ((8 - 1 - i)*8)); + r = r | ((uint64_t)(rbyte) << ((8 - 1 - i)*8)); } return r; @@ -147,11 +157,15 @@ uint64_t sd_read64(uint16_t * crc) { // This first initializes the SPI peripheral then initializes the SD // card itself. We use the uart to display anything that goes wrong. int init_sd(uint32_t freq, uint32_t sdclk){ + print_time(); + println("Initializing SPI Controller."); spi_init(); uint64_t r; uint32_t newClockDiv; + int n; + print_time(); println("Initializing SD Card in SPI mode."); // This is necessary. This is the card's pre-init state initialization. write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_OFF); @@ -165,31 +179,48 @@ int init_sd(uint32_t freq, uint32_t sdclk){ // Initializes SD card into SPI mode if CS is asserted '0' // We expect to get the R1 response 0x01 which means that the // card has been put into the idle state. + print_time(); print_uart("CMD0: "); + n = 0; do { r = CMD0(); + n++; + if (n == 1000) { + fail(); + } } while ( r != 0x01 ); println_with_r1("Success, r = 0x", r & 0xff); // CMD8 ------------------------------------------------------------- - // + // + print_time(); print_uart("CMD8: "); r = CMD8(); if ((r & 0x000000ff0000ffff) != 0x01000001aa) { println_with_r7("Failed, 0x", r); + fail(); } println_with_r7("Success, 0x", r); // ACMD41 ----------------------------------------------------------- + print_time(); print_uart("ACMD41: "); + n = 0; do { CMD55(); r = ACMD41(); + n++; + if (n == 1000) { + fail(); + } } while (r == 0x1); println_with_r1("Success, r = 0x", r & 0xff); + print_time(); println_with_dec("New clock frequency: ", (uint64_t)sdclk); spi_set_clock(freq, sdclk); + + print_time(); println("SD card is initialized."); } diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index b8829b12e..5b23c85b6 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -55,11 +55,15 @@ /* } */ uint8_t spi_txrx(uint8_t byte) { - spi_sendbyte(0xFF); + spi_sendbyte(byte); waittx(); return spi_readbyte(); } +uint8_t spi_dummy() { + return spi_txrx(0xff); +} + /* inline uint8_t spi_readbyte() { */ /* return read_reg(SPI_RXDATA); */ /* } */ diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index a662fce86..d2bf1191c 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -50,6 +50,7 @@ //inline void waittx(); //inline void waitrx(); uint8_t spi_txrx(uint8_t byte); +uint8_t spi_dummy(); //inline uint8_t spi_readbyte(); uint64_t spi_read64(); void spi_init(); diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index d7ac9b558..8c25f17ca 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -1,6 +1,5 @@ #include "uart.h" - void write_reg_u8(uintptr_t addr, uint8_t value) { volatile uint8_t *loc_addr = (volatile uint8_t *)addr; @@ -78,7 +77,7 @@ void print_uart_dec(uint64_t addr) { // floor(log(2^64)) = 19 char str[19] = {'\0'}; - uint8_t length = 0; + uint8_t length = 1; uint64_t cur = addr; while (cur != 0) { @@ -94,6 +93,43 @@ void print_uart_dec(uint64_t addr) { } } +// Print a floating point number on the UART +void print_uart_float(float num, int precision) { + char str[32] = {'\0'}; + char digit; + uint8_t length = precision + 1; + int i; + uint64_t cur; + + str[precision] = '.'; + + int pow = 1; + + // Calculate power for precision + for (i = 0; i < precision; i++) { + pow = pow * 10; + } + + cur = (uint64_t)(num * pow); + for (i = 0; i < precision; i++) { + digit = bin_to_hex_table[cur % 10]; + str[i] = digit; + cur = cur / 10; + } + + cur = (uint64_t)num; + do { + digit = bin_to_hex_table[cur % 10]; + str[length] = digit; + cur = cur/10; + length++; + } while (cur != 0); + + for (i = length; i > -1; i--) { + write_serial(str[i]); + } +} + /* void print_uart_int(uint32_t addr) */ /* { */ /* int i; */ diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index 515a9dccd..cbdcc5941 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -1,5 +1,7 @@ #pragma once #include <stdint.h> +#include "riscv.h" +#include "time.h" // UART register addresses #define UART_BASE 0x10000000 @@ -28,6 +30,8 @@ void print_uart_dec(uint64_t addr); void print_uart_addr(uint64_t addr); void print_uart_hex(uint64_t addr, int n); void print_uart_byte(uint8_t byte); +void print_uart_float(float num, int precision); +// void print_time(); // Print numbers in hex with specified widths #define print_uart_int(addr) print_uart_hex(addr, 4) @@ -44,4 +48,11 @@ void print_uart_byte(uint8_t byte); #define println_with_addr(msg, num) print_uart(msg); print_uart_addr(num); print_uart("\r\n") #define println_with_r1(msg, num) print_uart(msg); print_r1(num); print_uart("\r\n") #define println_with_r7(msg, num) print_uart(msg); print_r7(num); print_uart("\r\n") +#define println_with_float(msg, num) print_uart(msg); set_status_fs(); print_uart_float(num,5); clear_status_fs(); print_uart("\r\n") + +/* #define print_time() print_uart("["); \ */ +/* set_status_fs(); \ */ +/* print_uart_float(getTime(),5); \ */ +/* clear_status_fs(); \ */ +/* print_uart("] ") */ From 1e20d5aea66ff581f0e1b111aa03982a5daa5d95 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 2 Aug 2024 15:21:15 -0500 Subject: [PATCH 155/163] Added preload pointing to data.mem in ram1p1rwbe.sv --- src/generic/mem/ram1p1rwbe.sv | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index e2e76288b..287607c9e 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -89,6 +89,10 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE // end // end + `ifdef VERILATOR + import "DPI-C" function string getenvval(input string env_name); + `endif + initial if (PRELOAD_ENABLED) begin if (WIDTH == 64) begin From 11a057b0b35c849c7d184f957c228be957fcbb61 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 2 Aug 2024 15:33:57 -0500 Subject: [PATCH 156/163] Updated wally source files for zsbl testing. --- config/derivlist.txt | 3 ++- fpga/constraints/constraints-ArtyA7.xdc | 17 +++++++++++------ src/uncore/spi_apb.sv | 18 +++++++++++------- src/uncore/uncore.sv | 2 +- src/wally/wallypipelinedsoc.sv | 2 +- testbench/wallywrapper.sv | 16 ++++++++++------ 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/config/derivlist.txt b/config/derivlist.txt index 1edd20b7b..9d864f1f5 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -50,7 +50,8 @@ PLIC_NUM_SRC 32'd53 deriv fpga buildroot BOOTROM_PRELOAD 1 UNCORE_RAM_BASE 64'h2000 -UNCORE_RAM_RANGE 64'hFFF +UNCORE_RAM_RANGE 64'h1FFF +BOOTROM_RANGE 64'hFFF EXT_MEM_SUPPORTED 1 EXT_MEM_BASE 64'h80000000 EXT_MEM_RANGE 64'h0FFFFFFF diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 4e156601b..b8f98d430 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -97,16 +97,21 @@ set_property IOSTANDARD LVCMOS33 [get_ports {south_reset}] #set_property PULLUP true [get_ports {SDCCmd}] #set_property PULLUP true [get_ports {SDCCD}] -set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[3]}] -set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] -set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] -set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[0]}] +# SDCDat[3] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCS}] +# set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] +# set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] +# SDCDat[0] +set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCIn}] set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}] set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] -set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCDat[*]}] -set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCDat[*]}] +set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCCS}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCCS}] + +set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCIn}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCIn}] set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}] set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}] diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index e9c04bca8..cadb49dfb 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -148,6 +148,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // APB access assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase + // JACOB: This shouldn't behave this way assign PREADY = TransmitInactive; // Tie PREADY to transmission for hardware interlock // Account for subword read/write circuitry @@ -366,22 +367,25 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode)); assign Active0 = (state == ACTIVE_0); - // Signal tracks which edge of sck to shift data + // Signal tracks which edge of sck to shift data + // Jacob: We need to confirm that this represents the actual polarity and phase options for sampling. + // The first option now samples on the leading edge and shifts on the falling edge like it's supposed to. + // We need to confirm the validity of the other options. always_comb case(SckMode[1:0]) - 2'b00: ShiftEdge = ~SPICLK & SCLKenable; - 2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); - 2'b10: ShiftEdge = SPICLK & SCLKenable; - 2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); + 2'b00: ShiftEdge = SPICLK & SCLKenable; + 2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); // Probably wrong + 2'b10: ShiftEdge = ~SPICLK & SCLKenable; // Probably wrong + 2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); // Probably wrong default: ShiftEdge = SPICLK & SCLKenable; endcase // Transmit shift register assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0]; always_ff @(posedge PCLK) - if(~PRESETn) TransmitShiftReg <= 8'b0; + if(~PRESETn) TransmitShiftReg <= 8'b0; // Temporarily changing to 1s else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian; - else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0}; + else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], TransmitShiftReg[0]}; // Temporarily changing to 1s assign SPIOut = TransmitShiftReg[7]; diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 7de407c63..21dd956ed 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -172,7 +172,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr)); end else begin : sdc - assign SDCCmd = '0; assign SDCCS = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; + assign SDCCmd = '0; assign SDCCS = 4'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; end diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 7ad173b78..77845aff3 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -90,7 +90,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); end else begin assign {HRDATA, HREADY, HRESP, HSELEXT, MTimerInt, MSwInt, MExtInt, SExtInt, - MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; + MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS, SPICLK, SDCCmd, SDCCS, SDCCLK} = '0; end endmodule diff --git a/testbench/wallywrapper.sv b/testbench/wallywrapper.sv index 2794240be..b326bb810 100644 --- a/testbench/wallywrapper.sv +++ b/testbench/wallywrapper.sv @@ -32,7 +32,7 @@ module wallywrapper import cvw::*;( input logic clk, input logic reset_ext, input logic SPIIn, - input logic SDCIntr + input logic SDCIn ); `include "parameter-defs.vh" @@ -56,10 +56,14 @@ module wallywrapper import cvw::*;( logic UARTSin, UARTSout; logic SPIOut; logic [3:0] SPICS; + logic SPICLK; + + logic SDCCmd; + logic [3:0] SDCCS; + logic SDCCLK; logic HREADY; logic HSELEXT; - logic HSELEXTSDC; // instantiate device to be tested @@ -71,9 +75,9 @@ module wallywrapper import cvw::*;( assign HRDATAEXT = 0; - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, - .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, - .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr); + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, + .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, + .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); endmodule From 83b0a83d5cbe169f3e62b851e00084b9885a3990 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 2 Aug 2024 15:35:18 -0500 Subject: [PATCH 157/163] Removed HSELEXTSDC and fixed SD card pin definitions. --- fpga/src/fpgaTopArtyA7.sv | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 31848f33e..712f67869 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -42,10 +42,11 @@ module fpgaTop output UARTSout, // SDC Signals connecting to an SPI peripheral - input [3:0] SDCDat, + input SDCIn, output SDCCLK, output SDCCmd, - output SDCCD, + output SDCCS, + input SDCCD, // Memory signals inout [15:0] ddr3_dq, @@ -199,10 +200,8 @@ module fpgaTop assign cpu_reset = bus_struct_reset; assign calib = c0_init_calib_complete; - logic [3:0] SDCCS; - assign SDCCD = SDCCS[0]; - logic SDCIn; - assign SDCIn = SDCDat[0]; + logic [3:0] SDCCSin; + assign SDCCS = SDCCSin[0]; // mmcm @@ -243,14 +242,14 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); + .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK); // ahb lite to axi bridge xlnx_ahblite_axi_bridge xlnx_ahblite_axi_bridge_0 (.s_ahb_hclk(CPUCLK), .s_ahb_hresetn(peripheral_aresetn), - .s_ahb_hsel(HSELEXT | HSELEXTSDC), + .s_ahb_hsel(HSELEXT), .s_ahb_haddr(HADDR[31:0]), .s_ahb_hprot(HPROT), .s_ahb_htrans(HTRANS), From ad9c98c19cd46a3f05fc26d086f70b1faead83e7 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Fri, 2 Aug 2024 15:36:06 -0500 Subject: [PATCH 158/163] Added file necessary to split boot.mem into boot.mem and data.mem. --- fpga/zsbl/splitfile.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 fpga/zsbl/splitfile.sh diff --git a/fpga/zsbl/splitfile.sh b/fpga/zsbl/splitfile.sh new file mode 100755 index 000000000..1e367c872 --- /dev/null +++ b/fpga/zsbl/splitfile.sh @@ -0,0 +1,18 @@ +# Acquired from here. +# https://stackoverflow.com/questions/3066948/how-to-file-split-at-a-line-number +file_name=$1 + +# set first K lines: +K=512 + +# line count (N): +N=$(wc -l < $file_name) + +# length of the bottom file: +L=$(( $N - $K )) + +# create the top of file: +head -n $K $file_name > boot.mem + +# create bottom of file: +tail -n $L $file_name > data.mem From 665396fdb3f1b8d0435207987c9b04926d1e9db1 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 6 Aug 2024 16:57:57 -0500 Subject: [PATCH 159/163] SD card is now mountable on the fpga. The relevant files have been added. The most important changes are in the buildroot linux configuration and device tree. --- fpga/constraints/constraints-ArtyA7.xdc | 8 ++- fpga/src/fpgaTopArtyA7.sv | 3 +- fpga/zsbl/boot.c | 2 +- linux/Makefile | 2 +- .../buildroot-2023.05.1/linux.config | 13 ++--- linux/devicetree/wally-artya7.dts | 51 ++++++++++++++----- 6 files changed, 55 insertions(+), 24 deletions(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index b8f98d430..394c58dda 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -35,6 +35,7 @@ set_property IOSTANDARD LVCMOS33 [get_ports {GPO[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPO[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPO[0]}] set_max_delay -to [get_ports {GPO[*]}] 20.000 + set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 0.000 [get_ports {GPO[*]}] @@ -106,18 +107,21 @@ set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports { set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}] set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] +set_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCWP}] + set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCCS}] -set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCCS}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 10.000 [get_ports {SDCCS}] set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCIn}] -set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCIn}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 10.000 [get_ports {SDCIn}] set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}] set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}] set_output_delay -clock [get_clocks SPISDCClock] 0.000 [get_ports SDCCLK] + #set_multicycle_path -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 10 set_max_delay -datapath_only -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 20.000 diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 712f67869..5d038ad0f 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -47,6 +47,7 @@ module fpgaTop output SDCCmd, output SDCCS, input SDCCD, + input SDCWP, // Memory signals inout [15:0] ddr3_dq, @@ -194,7 +195,7 @@ module fpgaTop wire mmcm1_locked; - assign GPIOIN = {28'b0, GPI}; + assign GPIOIN = {25'b0, SDCCD, SDCWP, 1'b0, GPI}; assign GPO = GPIOOUT[4:0]; assign ahblite_resetn = peripheral_aresetn; assign cpu_reset = bus_struct_reset; diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index e47b34e2f..52473ab46 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -159,7 +159,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { /* print_uart("\r\n"); */ // Intialize the SD card - init_sd(SYSTEMCLOCK, 3000000); + init_sd(SYSTEMCLOCK, 5000000); ret = gpt_load_partitions(); } diff --git a/linux/Makefile b/linux/Makefile index 6f7b6c7fb..b0b15ce7b 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -102,7 +102,7 @@ $(IMAGES)/busybox: # Generating new Buildroot directories -------------------------------- # This directive should be run as: make install BUILDROOT=path/to/buildroot -download: $(BUILDROOT)/package/fpga-axi-sdc $(WALLYBOARD) +download: $(WALLYBOARD) cp $(WALLYBOARD)/main.config $(BUILDROOT)/.config # CONFIG DEPENDENCIES 2023.05.1 --------------------------------------- diff --git a/linux/buildroot-config-src/buildroot-2023.05.1/linux.config b/linux/buildroot-config-src/buildroot-2023.05.1/linux.config index e348cde78..047be24c2 100644 --- a/linux/buildroot-config-src/buildroot-2023.05.1/linux.config +++ b/linux/buildroot-config-src/buildroot-2023.05.1/linux.config @@ -2,7 +2,7 @@ # Automatically generated file; DO NOT EDIT. # Linux/riscv 6.6.0 Kernel Configuration # -CONFIG_CC_VERSION_TEXT="riscv64-buildroot-linux-gnu-gcc.br_real (Buildroot 2023.05.3-dirty) 12.3.0" +CONFIG_CC_VERSION_TEXT="riscv64-buildroot-linux-gnu-gcc.br_real (Buildroot 2023.05.3) 12.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=120300 CONFIG_CLANG_VERSION=0 @@ -1042,7 +1042,7 @@ CONFIG_MMC_BLOCK_MINORS=8 # # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_SPI is not set +CONFIG_MMC_SPI=y # CONFIG_MMC_DW is not set # CONFIG_MMC_USDHI6ROL0 is not set # CONFIG_MMC_CQHCI is not set @@ -1455,7 +1455,7 @@ CONFIG_CRYPTO_HASH2=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_SHA3 is not set # CONFIG_CRYPTO_SM3_GENERIC is not set @@ -1527,13 +1527,14 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 # CONFIG_CRYPTO_LIB_POLY1305 is not set # CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y # end of Crypto library routines # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set # CONFIG_CRC64_ROCKSOFT is not set -# CONFIG_CRC_ITU_T is not set +CONFIG_CRC_ITU_T=y CONFIG_CRC32=y # CONFIG_CRC32_SELFTEST is not set CONFIG_CRC32_SLICEBY8=y @@ -1542,7 +1543,7 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_BIT is not set # CONFIG_CRC64 is not set # CONFIG_CRC4 is not set -# CONFIG_CRC7 is not set +CONFIG_CRC7=y # CONFIG_LIBCRC32C is not set # CONFIG_CRC8 is not set # CONFIG_RANDOM32_SELFTEST is not set @@ -1599,7 +1600,7 @@ CONFIG_PRINTK_TIME=y # CONFIG_STACKTRACE_BUILD_ID is not set CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_CONSOLE_LOGLEVEL_QUIET=4 -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DYNAMIC_DEBUG_CORE is not set diff --git a/linux/devicetree/wally-artya7.dts b/linux/devicetree/wally-artya7.dts index 87933bcc0..99b8ff00d 100644 --- a/linux/devicetree/wally-artya7.dts +++ b/linux/devicetree/wally-artya7.dts @@ -5,11 +5,11 @@ #size-cells = <0x02>; compatible = "wally-virt"; model = "wally-virt,qemu"; - + chosen { linux,initrd-end = <0x85c43a00>; linux,initrd-start = <0x84200000>; - bootargs = "root=/dev/vda ro console=ttyS0,115200"; + bootargs = "root=/dev/vda ro console=ttyS0,115200 loglevel=7"; stdout-path = "/soc/uart@10000000"; }; @@ -51,6 +51,25 @@ compatible = "simple-bus"; ranges; + refclk: refclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0x1312D00>; + clock-output-names = "xtal"; + }; + + gpio0: gpio@10060000 { + compatible = "sifive,gpio0"; + interrupt-parent = <0x03>; + interrupts = <3>; + reg = <0x00 0x10060000 0x00 0x1000>; + reg-names = "control"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + uart@10000000 { interrupts = <0x0a>; interrupt-parent = <0x03>; @@ -70,18 +89,24 @@ #address-cells = <0x00>; }; - mmc@13000 { - interrupts = <0x14>; - compatible = "riscv,axi-sd-card-1.0"; - reg = <0x00 0x13000 0x00 0x7F>; - fifo-depth = <256>; - bus-width = <4>; + spi@13000 { + compatible = "sifive,spi0"; interrupt-parent = <0x03>; - clock = <0x1312D00>; - max-frequency = <0x1312D00>; - cap-sd-highspeed; - cap-mmc-highspeed; - no-sdio; + interrupts = <0x14>; + reg = <0x0 0x13000 0x0 0x1000>; + reg-names = "control"; + clocks = <&refclk>; + + #address-cells = <1>; + #size-cells = <0>; + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + spi-max-frequency = <5000000>; + voltage-ranges = <3300 3300>; + disable-wp; + // gpios = <&gpio0 6 1>; + }; }; clint@2000000 { From 954e21148f8aac040f9ed9d8742b1d58754276e2 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 6 Aug 2024 17:11:08 -0500 Subject: [PATCH 160/163] Removed line referring to local file in wally.tcl. --- fpga/generator/wally.tcl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index 465d0c73a..b2e1e359e 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -92,8 +92,7 @@ if {$board=="ArtyA7"} { #source ../constraints/small-debug.xdc source ../constraints/small-debug-rvvi.xdc } else { - # source ../constraints/vcu-small-debug.xdc - source ../constraints/debug6.xdc + source ../constraints/vcu-small-debug.xdc } From 280b5baa59a5fdad57e1cae8eec4ef3f199c5da2 Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 6 Aug 2024 17:28:50 -0500 Subject: [PATCH 161/163] Added header to new bootloader files. --- fpga/zsbl/boot.c | 77 ++++++++++++++++++----------------------------- fpga/zsbl/boot.h | 29 ++++++++++++++++++ fpga/zsbl/fail.c | 30 ++++++++++++++++++ fpga/zsbl/fail.h | 29 ++++++++++++++++++ fpga/zsbl/gpt.c | 29 ++++++++++++++++++ fpga/zsbl/gpt.h | 29 ++++++++++++++++++ fpga/zsbl/riscv.S | 29 ++++++++++++++++++ fpga/zsbl/riscv.h | 29 ++++++++++++++++++ fpga/zsbl/sd.c | 29 ++++++++++++++++++ fpga/zsbl/sd.h | 30 ++++++++++++++++++ fpga/zsbl/spi.c | 29 ------------------ fpga/zsbl/time.c | 29 ++++++++++++++++++ fpga/zsbl/time.h | 29 ++++++++++++++++++ fpga/zsbl/uart.c | 30 ++++++++++++++++++ fpga/zsbl/uart.h | 29 ++++++++++++++++++ 15 files changed, 409 insertions(+), 77 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 52473ab46..566393cb6 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// boot.c +// +// Written: Jacob Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Main bootloader entry point +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include <stddef.h> #include "boot.h" #include "gpt.h" @@ -8,54 +37,6 @@ #include "riscv.h" #include "fail.h" -/* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ - -/* /\* This is not needed. This has everything to do with the FAT */ -/* filesystem stuff that I'm not including. All I need to do is */ -/* initialize the SD card and read from it. Anything in here that is */ -/* checking for potential errors, I'm going to have to temporarily */ -/* do without. */ -/* *\/ */ -/* // if (!count) return RES_PARERR; */ -/* /\* if (drv_status & STA_NOINIT) return RES_NOTRDY; *\/ */ - -/* uint32_t response[4]; */ -/* struct sdc_regs * regs = (struct sdc_regs *)SDC; */ - -/* /\* Convert LBA to byte address if needed *\/ */ -/* if (!(card_type & CT_BLOCK)) sector *= 512; */ -/* while (count > 0) { */ -/* UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; */ -/* unsigned bytes = bcnt * 512; */ -/* if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; */ -/* if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; */ -/* sector += (card_type & CT_BLOCK) ? bcnt : bytes; */ -/* count -= bcnt; */ -/* buf += bytes; */ -/* } */ - -/* return 0;; */ -/* } */ - -// Need to convert this -/* void print_progress(size_t count, size_t max) { */ -/* const int bar_width = 50; */ - -/* float progress = (float) count / max; */ -/* int bar_length = progress * bar_width; */ - -/* printf("\r["); */ -/* for (int i = 0; i < bar_length; ++i) { */ -/* printf("#"); */ -/* } */ -/* for (int i = bar_length; i < bar_width; ++i) { */ -/* printf("-"); */ -/* } */ -/* printf("] %.2f%%", progress * 100); */ - -/* fflush(stdout); */ -/* } */ - int disk_read(BYTE * buf, LBA_t sector, UINT count) { uint64_t r; UINT i; diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 25b8a5fcc..0c09a1e52 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// boot.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header for boot.c, main bootloader entry point +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #ifndef WALLYBOOT #define WALLYBOOT 10000 diff --git a/fpga/zsbl/fail.c b/fpga/zsbl/fail.c index 4e6cd8db0..4430c4a8f 100644 --- a/fpga/zsbl/fail.c +++ b/fpga/zsbl/fail.c @@ -1,3 +1,33 @@ +/////////////////////////////////////////////////////////////////////// +// fail.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Prints information on the uart when a fatal bug is +// encountered. Will expand this later. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include "fail.h" #include "uart.h" #include "riscv.h" diff --git a/fpga/zsbl/fail.h b/fpga/zsbl/fail.h index da1a2e405..c965265d1 100644 --- a/fpga/zsbl/fail.h +++ b/fpga/zsbl/fail.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// fail.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Function prototype for fail, +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #pragma once #include <stdint.h> diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 99f74ec3a..e21176f05 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// gpt.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Code to read GPT Partitions off of an SD card. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include "gpt.h" #include "boot.h" #include "uart.h" diff --git a/fpga/zsbl/gpt.h b/fpga/zsbl/gpt.h index 5ce5e1d4b..8cd3ecc11 100644 --- a/fpga/zsbl/gpt.h +++ b/fpga/zsbl/gpt.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// gpt.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header for gpt.c, contains gpt structs +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #pragma once #include <stdint.h> diff --git a/fpga/zsbl/riscv.S b/fpga/zsbl/riscv.S index 7f400b1b2..b2d86599c 100644 --- a/fpga/zsbl/riscv.S +++ b/fpga/zsbl/riscv.S @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// riscv.S +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Basic utility functions for reading registers +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + .section .text .globl read_mcycle .type read_mcycle, @function diff --git a/fpga/zsbl/riscv.h b/fpga/zsbl/riscv.h index a27cd48d6..543fe5cde 100644 --- a/fpga/zsbl/riscv.h +++ b/fpga/zsbl/riscv.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// riscv.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Function prototypes for riscv utility functions +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #pragma once #include <stdint.h> diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 484fd65c0..1f95d8477 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// sd.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: SD Card protocol functions +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include "sd.h" #include "spi.h" #include "uart.h" diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index f695b83e5..f66686560 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -1,3 +1,33 @@ +/////////////////////////////////////////////////////////////////////// +// sd.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header file for SD card protocol functions. Defines some +// useful macros. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #pragma once #include <stdint.h> diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 5b23c85b6..04d609648 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -29,31 +29,6 @@ #include "spi.h" -// Write to a register -/* inline void write_reg(uintptr_t addr, uint32_t value) { */ -/* volatile uint32_t * loc = (volatile uint32_t *) addr; */ -/* *loc = value; */ -/* } */ - -/* // Read a register */ -/* inline uint32_t read_reg(uintptr_t addr) { */ -/* return *(volatile uint32_t *) addr; */ -/* } */ - -/* // Queues a single byte in the transfer fifo */ -/* inline void spi_sendbyte(uint8_t byte) { */ -/* // Write byte to transfer fifo */ -/* write_reg(SPI_TXDATA, byte); */ -/* } */ - -/* inline void waittx() { */ -/* while(!(read_reg(SPI_IP) & 1)) {} */ -/* } */ - -/* inline void waitrx() { */ -/* while(read_reg(SPI_IP) & 2) {} */ -/* } */ - uint8_t spi_txrx(uint8_t byte) { spi_sendbyte(byte); waittx(); @@ -64,10 +39,6 @@ uint8_t spi_dummy() { return spi_txrx(0xff); } -/* inline uint8_t spi_readbyte() { */ -/* return read_reg(SPI_RXDATA); */ -/* } */ - uint64_t spi_read64() { uint64_t r; uint8_t rbyte; diff --git a/fpga/zsbl/time.c b/fpga/zsbl/time.c index 43ac085b7..c265eea05 100644 --- a/fpga/zsbl/time.c +++ b/fpga/zsbl/time.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// time.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Gets and prints the current time. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include "time.h" #include "boot.h" #include "riscv.h" diff --git a/fpga/zsbl/time.h b/fpga/zsbl/time.h index 6cd928b88..8bf7064af 100644 --- a/fpga/zsbl/time.h +++ b/fpga/zsbl/time.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// spi.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Time function prototypes +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #pragma once #include <stdint.h> diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index 8c25f17ca..580265d98 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -1,3 +1,33 @@ +/////////////////////////////////////////////////////////////////////// +// uart.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Uart printing functions, as well as functions for printing +// hex, decimal, and floating point numbers. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #include "uart.h" void write_reg_u8(uintptr_t addr, uint8_t value) diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index cbdcc5941..96c55ffe8 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// uart.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header for the UART functions. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// distributed under the License is distributed on an “AS IS” BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +/////////////////////////////////////////////////////////////////////// + #pragma once #include <stdint.h> #include "riscv.h" From 2dc7e0f76fa4cceca5fffc8612244365f7e9c40a Mon Sep 17 00:00:00 2001 From: Jacob Pease <jacobpease@protonmail.com> Date: Tue, 6 Aug 2024 17:36:42 -0500 Subject: [PATCH 162/163] Added and extra header and changed the comments to be accurate in ram1p1rwbe.sv --- fpga/zsbl/splitfile.sh | 32 +++++++++++++++++++++++++++++++- src/generic/mem/ram1p1rwbe.sv | 6 +++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/fpga/zsbl/splitfile.sh b/fpga/zsbl/splitfile.sh index 1e367c872..fc943576c 100755 --- a/fpga/zsbl/splitfile.sh +++ b/fpga/zsbl/splitfile.sh @@ -1,5 +1,35 @@ +####################################################################### +# splitfile.sh +# +# Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +# +# Purpose: Used to split boot.mem into two sections for FPGA +# +# +# +# A component of the Wally configurable RISC-V project. +# +# Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +# +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# +# Licensed under the Solderpad Hardware License v 2.1 (the +# “License”); you may not use this file except in compliance with the +# License, or, at your option, the Apache License version 2.0. You +# may obtain a copy of the License at +# +# https://solderpad.org/licenses/SHL-2.1/ +# +# Unless required by applicable law or agreed to in writing, any work +# distributed under the License is distributed on an “AS IS” BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +###################################################################### + + # Acquired from here. -# https://stackoverflow.com/questions/3066948/how-to-file-split-at-a-line-number +# https:##stackoverflow.com#questions#3066948#how-to-file-split-at-a-line-number file_name=$1 # set first K lines: diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index 287607c9e..d17262d22 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -99,11 +99,11 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE `ifdef VERILATOR // because Verilator doesn't automatically accept $WALLY from shell string WALLY_DIR = getenvval("WALLY"); - $readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + $readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA `else - $readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + $readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA `endif - end else begin // put something in the ROM so it is not optimized away + end else begin // put something in the RAM so it is not optimized away RAM[0] = 'h00002197; end end From 0303314f4e34c6aee826d17283cc877c22460bf7 Mon Sep 17 00:00:00 2001 From: Huda-10xe <huda.sajjad@10xengineers.ai> Date: Wed, 7 Aug 2024 14:19:05 +0500 Subject: [PATCH 163/163] Adding RVVI Functional Coverage Support --- .gitignore | 3 +++ .gitmodules | 3 +++ bin/regression-wally | 12 ++++++++++++ bin/wsim | 7 +++++-- cvw-arch-verif | 1 + sim/questa/wally.do | 21 ++++++++++++++++++++- testbench/testbench.sv | 12 ++++++++++++ tests/riscof/Makefile | 9 +++++++++ 8 files changed, 65 insertions(+), 3 deletions(-) create mode 160000 cvw-arch-verif diff --git a/.gitignore b/.gitignore index 3a6dad8b0..3d3d875f0 100644 --- a/.gitignore +++ b/.gitignore @@ -193,6 +193,9 @@ config/deriv docs/docker/buildroot-config-src docs/docker/testvector-generation sim/questa/cov +sim/questa/fcovrvvi +sim/questa/fcovrvvi_logs +sim/questa/fcovrvvi_ucdb sim/covhtmlreport/ sim/questa/logs sim/questa/wkdir diff --git a/.gitmodules b/.gitmodules index 69054d830..e2c94791f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,6 @@ sparseCheckout = true path = addins/verilog-ethernet url = https://github.com/ross144/verilog-ethernet.git +[submodule "cvw-arch-verif"] + path = cvw-arch-verif + url = https://github.com/openhwgroup/cvw-arch-verif diff --git a/bin/regression-wally b/bin/regression-wally index 3040f584b..e83c3b5fa 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -340,6 +340,7 @@ defaultsim = "verilator" # Default simulator for all other tests parser = argparse.ArgumentParser() parser.add_argument("--ccov", help="Code Coverage", action="store_true") parser.add_argument("--fcov", help="Functional Coverage", action="store_true") +parser.add_argument("--fcovrvvi", help="Functional Coverage RVVI", action="store_true") parser.add_argument("--nightly", help="Run large nightly regression", action="store_true") parser.add_argument("--buildroot", help="Include Buildroot Linux boot test (takes many hours, done along with --nightly)", action="store_true") parser.add_argument("--testfloat", help="Include Testfloat floating-point unit tests", action="store_true") @@ -357,6 +358,8 @@ if (args.ccov): # only run RV64GC tests in coverage mode coverStr = '--ccov' elif (args.fcov): # only run RV64GC tests in lockstep in coverage mode coverStr = '--fcov' +elif (args.fcovrvvi): # only run RV64GC tests in rvvi coverage mode + coverStr = '--fcovrvvi' else: coverStr = '' @@ -392,6 +395,10 @@ elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional c # grepstr="SUCCESS! All tests ran without failures", # grepfile = sim_log) #configs.append(tc) +elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode + addTests(tests64gc_nofp, coveragesim) + if (args.fp): + addTests(tests64gc_fp, coveragesim) else: for sim in sims: if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one @@ -501,6 +508,9 @@ def main(): if args.ccov: TIMEOUT_DUR = 20*60 # seconds os.system('rm -f questa/cov/*.ucdb') + elif args.fcovrvvi: + TIMEOUT_DUR = 20*60 + os.system('rm -f questa/fcovrvvi_ucdb/* questa/fcovrvvi_logs/* questa/fcovrvvi/*') elif args.fcov: TIMEOUT_DUR = 1*60 os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*') @@ -535,6 +545,8 @@ def main(): os.system('make QuestaCodeCoverage') if args.fcov: os.system('make QuestaFunctCoverage') + if args.fcovrvvi: + os.system('make QuestaFunctCoverageRvvi') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/bin/wsim b/bin/wsim index b2288deb4..d837bca85 100755 --- a/bin/wsim +++ b/bin/wsim @@ -28,6 +28,7 @@ parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testb parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") parser.add_argument("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true") +parser.add_argument("--fcovrvvi", "-fr", help="Functional Coverage RVVI", action="store_true") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true") parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") @@ -57,7 +58,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che # Validate arguments -if (args.gui or args.ccov or args.fcov or args.lockstep): +if (args.gui or args.ccov or args.fcov or args.fcovrvvi or args.lockstep): if args.sim not in ["questa", "vcs"]: print("Option only supported for Questa and VCS") exit(1) @@ -95,10 +96,12 @@ if (args.ccov): flags += " --ccov" if (args.fcov): flags += " --fcov" +if (args.fcovrvvi): + flags += "--fcovrvvi" # create the output sub-directories. regressionDir = WALLY + '/sim/' -for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb"]: +for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb", "fcovrvvi", "fcovrvvi_ucdb"]: try: os.mkdir(regressionDir+args.sim+"/"+d) except: diff --git a/cvw-arch-verif b/cvw-arch-verif new file mode 160000 index 000000000..2a4f56ec9 --- /dev/null +++ b/cvw-arch-verif @@ -0,0 +1 @@ +Subproject commit 2a4f56ec97db7cdd6fd13fb928122d408fefbf1e diff --git a/sim/questa/wally.do b/sim/questa/wally.do index 632e2c156..43892c356 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -31,6 +31,7 @@ set WALLY $::env(WALLY) set CONFIG ${WALLY}/config set SRC ${WALLY}/src set TB ${WALLY}/testbench +set FCRVVI ${WALLY}/addins/cvw-arch-verif/fcov # create library if [file exists ${WKDIR}] { @@ -39,11 +40,16 @@ if [file exists ${WKDIR}] { vlib ${WKDIR} # Create directory for coverage data mkdir -p cov +# Create directory for functional coverage data +mkdir ${WALLY}/addins/cvw-arch-verif/work set ccov 0 set CoverageVoptArg "" set CoverageVsimArg "" +set FuncCovRVVI 0 +set FCdefineRVVI_COVERAGE "" + set FunctCoverage 0 set riscvISACOVsrc "" set FCdefineINCLUDE_TRACE2COV "" @@ -113,6 +119,13 @@ if {$CoverageIndex >= 0} { set lst [lreplace $lst $CoverageIndex $CoverageIndex] } +set FCoverageIndexRVVI [lsearch -exact $lst "--fcovrvvi"] +if {$FCoverageIndexRVVI >= 0} { + set FuncCovRVVI 1 + set FCdefineRVVI_COVERAGE "+define+RVVI_COVERAGE" + set lst [lreplace $lst $FCoverageIndexRVVI $FCoverageIndexRVVI] +} + # if +coverage found set flag and remove from list set FunctCoverageIndex [lsearch -exact $lst "--fcov"] if {$FunctCoverageIndex >= 0} { @@ -172,6 +185,7 @@ if {$DEBUG > 0} { echo "GUI = $GUI" echo "ccov = $ccov" echo "lockstep = $lockstep" + echo "FuncCovRVVI = $FuncCovRVVI" echo "FunctCoverage = $FunctCoverage" echo "remaining list = $lst" echo "Extra +args = $PlusArgs" @@ -197,7 +211,7 @@ set temp3 [lindex $PlusArgs 3] # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 +vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${FCdefineRVVI_COVERAGE} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv +incdir+${FCRVVI}/common +incdir+${FCRVVI} ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals @@ -224,6 +238,11 @@ if {$FunctCoverage} { coverage save -onexit ${UCDB} } +if {$FuncCovRVVI} { + set UCDB ${WALLY}/addins/cvw-arch-verif/work/${CFG}_${TESTSUITE}.ucdb + coverage save -onexit ${UCDB} +} + run -all if {$ccov} { diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 89d3b06d5..c53e0a842 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -33,6 +33,12 @@ `include "idv/idv.svh" `endif +`ifdef RVVI_COVERAGE + `include "RISCV_trace_data.svh" + `include "rvvicov.svh" + `include "wrapper.sv" +`endif + import cvw::*; module testbench; @@ -982,6 +988,12 @@ test_pmp_coverage #(P) pmp_inst(clk); /* verilator lint_on WIDTHTRUNC */ /* verilator lint_on WIDTHEXPAND */ +`ifdef RVVI_COVERAGE + rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi(); + wallyTracer #(P) wallyTracer(rvvi); + wrapper #(P) wrap(clk); +`endif + endmodule /* verilator lint_on STMTDLY */ diff --git a/tests/riscof/Makefile b/tests/riscof/Makefile index aaa8a8344..1d42cf10c 100644 --- a/tests/riscof/Makefile +++ b/tests/riscof/Makefile @@ -4,13 +4,18 @@ work_dir = ./riscof_work work = ./work arch_workdir = $(work)/riscv-arch-test wally_workdir = $(work)/wally-riscv-arch-test +custom_test_dir = ../../addins/cvw-arch-verif/test +submodule_work_dir = ../../addins/cvw-arch-verif/riscof_work current_dir = $(shell pwd) #XLEN ?= 64 all: root arch32 wally32 arch32e arch64 wally64 + wally-riscv-arch-test: root wally64 wally32 +custom: new_test + root: mkdir -p $(work_dir) mkdir -p $(work) @@ -47,6 +52,9 @@ wally64: quad64: riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests/ --env=$(wally_dir)/riscv-test-suite/env + +new_test: + riscof run --work-dir=$(submodule_work_dir) --config=config64.ini --suite=$(custom_test_dir)/ --env=$(wally_dir)/riscv-test-suite/env --no-browser #wally32e: # riscof run --work-dir=$(work_dir) --config=config32e.ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run @@ -66,3 +74,4 @@ clean: rm -rf $(work_dir) rm -rf $(wally_workdir) rm -rf $(arch_workdir) + rm -rf $(submodule_wor_dir)