From d66a613074f609962cc56506fd0ccfdd5c6bcdeb Mon Sep 17 00:00:00 2001 From: Huda-10xe Date: Mon, 28 Oct 2024 00:32:07 -0700 Subject: [PATCH 01/42] Renaming VM Coverage --- config/rv32gc/coverage.svh | 3 ++- config/rv64gc/coverage.svh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/rv32gc/coverage.svh b/config/rv32gc/coverage.svh index 3a04643ad..415722efc 100644 --- a/config/rv32gc/coverage.svh +++ b/config/rv32gc/coverage.svh @@ -13,4 +13,5 @@ `include "RV32Zca_coverage.svh" `include "RV32Zcb_coverage.svh" `include "RV32ZcbM_coverage.svh" -`include "RV32ZcbZbb_coverage.svh" \ No newline at end of file +`include "RV32ZcbZbb_coverage.svh" +`include "VM_coverage.svh" \ No newline at end of file diff --git a/config/rv64gc/coverage.svh b/config/rv64gc/coverage.svh index 5b11b5a22..ed337a4ac 100644 --- a/config/rv64gc/coverage.svh +++ b/config/rv64gc/coverage.svh @@ -9,7 +9,7 @@ `include "RV64M_coverage.svh" `include "RV64F_coverage.svh" `include "RV64Zfh_coverage.svh" -`include "RV64VM_coverage.svh" +`include "VM_coverage.svh" `include "RV64VM_PMP_coverage.svh" `include "RV64CBO_VM_coverage.svh" `include "RV64CBO_PMP_coverage.svh" From 3f94fc3ca245604e71d0f8537127749cfc1bf8e9 Mon Sep 17 00:00:00 2001 From: Huda-10xe Date: Tue, 29 Oct 2024 03:13:53 -0700 Subject: [PATCH 02/42] Changing VM covergae name to incorporate sv32 coverpoints --- config/rv64gc/coverage.svh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/rv64gc/coverage.svh b/config/rv64gc/coverage.svh index 20d5108d6..4e863b288 100644 --- a/config/rv64gc/coverage.svh +++ b/config/rv64gc/coverage.svh @@ -21,7 +21,7 @@ `include "RV64Zcd_coverage.svh" // Privileged extensions -`include "RVVM_coverage.svh" +`include "VM_coverage.svh" `include "ZicsrM_coverage.svh" // `include "RV64VM_PMP_coverage.svh" // `include "RV64CBO_VM_coverage.svh" From 8515c20c158c02e5202a753e565a38b690703e10 Mon Sep 17 00:00:00 2001 From: Huda-10xe Date: Tue, 29 Oct 2024 04:25:02 -0700 Subject: [PATCH 03/42] Removing VM_Covergae from this till its complete --- config/rv32gc/coverage.svh | 1 - 1 file changed, 1 deletion(-) diff --git a/config/rv32gc/coverage.svh b/config/rv32gc/coverage.svh index 96362fdf3..217e8788a 100644 --- a/config/rv32gc/coverage.svh +++ b/config/rv32gc/coverage.svh @@ -22,4 +22,3 @@ // Privileged extensions `include "ZicsrM_coverage.svh" -`include "VM_coverage.svh" From 896bb21f7c7d839904c20df5510e7fa49899fbd7 Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Tue, 29 Oct 2024 09:58:53 -0500 Subject: [PATCH 04/42] Added potential test. btbthrash forces jump and divide instructions to occupy the same location in the btb. Instruction class prediction mispredicts ever time. This is useful incase someone changes the hazard code or fpu. --- tests/coverage/btbthrash.S | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tests/coverage/btbthrash.S diff --git a/tests/coverage/btbthrash.S b/tests/coverage/btbthrash.S new file mode 100644 index 000000000..8fedf372a --- /dev/null +++ b/tests/coverage/btbthrash.S @@ -0,0 +1,145 @@ +/////////////////////////////////////////// +// btbtrash.S +// +// Written: Rose Thompson rose@rosethompson.net 23 October 2024 +// +// Purpose: Test the branch target buffer alias with divide and cache pipeline stalls +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// + +// load code to initalize stack, handle interrupts, terminate +#include "WALLY-init-lib.h" + +main: + + # Division test (having trouble with buildroot) + li x1, 1938759018 + li x2, 3745029 + li x3, 458 + li x4, 29587209347 + li x5, 28957 + li x6, 298 + li x7, 238562 + li x8, 198674 + li x9, 134 + li x10, 906732 + li x11, 29 + li x12, 50912 + li x13, 59 + li x14, 6902385 + li x15, 1923857 + li x16, 3985 + li x17, 3947 + li x18, 15984 + li x19, 5 + li x20, 9684658489 + li x21, 6548 + li x22, 3564 + li x23, 94 + li x24, 689464 + li x25, 42567 + li x26, 98453 + li x27, 648 + li x28, 984 + li x29, 6984 + li x30, 864 + + # x31 will be our loop counter + li x31, 4 + +.align 12 +jump1: + divuw x0, x1, x2 + j jump3 +jump4: + divuw x0, x5, x6 + j jump5 +jump6: + divuw x0, x10, x9 + j jump7 +jump8: + divuw x0, x14, x3 + j jump9 +jump10: + divuw x0, x18, x17 + j jump11 +jump12: + divuw x0, x21, x22 + j jump13 +jump14: + divuw x0, x24, x25 + j jump15 +jump16: + divuw x0, x29, x28 + j jump17 +jump18: + divuw x0, x1, x30 + j jump19 +jump20: + divuw x0, x3, x19 + j jump21 +jump22: + divuw x0, x12, x13 + j jump23 + +.align 12 # size of the 1024 btb apart +jump2: + j jump1 +jump3: + divuw x0, x4, x3 + j jump4 +jump5: + divuw x0, x7, x8 + j jump6 +jump7: + divuw x0, x12, x11 + j jump8 +jump9: + divuw x0, x15, x16 + j jump10 +jump11: + divuw x0, x20, x19 + j jump12 +jump13: + divuw x0, x24, x23 + j jump14 +jump15: + divuw x0, x26, x27 + j jump16 +jump17: + divuw x0, x29, x30 + j jump18 +jump19: + divuw x0, x2, x3 + j jump20 +jump21: + divuw x0, x4, x5 + j jump22 +jump23: + divuw x0, x20, x21 + #j jump22 + + fence.i + + addi x31, x31, -1 + bne x31, x0, jump1 +finsihed: + j done + From af74635216eeca9dca33d49c25b7a9206f23a71c Mon Sep 17 00:00:00 2001 From: Huda-10xe Date: Tue, 29 Oct 2024 09:44:18 -0700 Subject: [PATCH 05/42] reverting VM to RV64VM --- config/rv64gc/coverage.svh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/rv64gc/coverage.svh b/config/rv64gc/coverage.svh index 4e863b288..0491b4ab3 100644 --- a/config/rv64gc/coverage.svh +++ b/config/rv64gc/coverage.svh @@ -21,7 +21,7 @@ `include "RV64Zcd_coverage.svh" // Privileged extensions -`include "VM_coverage.svh" +`include "RV64VM_coverage.svh" `include "ZicsrM_coverage.svh" // `include "RV64VM_PMP_coverage.svh" // `include "RV64CBO_VM_coverage.svh" From 7405456de5da940621b79f32a3f0e0ed7fc5c0b7 Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Tue, 29 Oct 2024 15:47:24 -0500 Subject: [PATCH 06/42] added script to install libncurses5 and libtinfo5 for ubuntu24.04. --- bin/vivado-ubuntu24.04-libs.sh | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100755 bin/vivado-ubuntu24.04-libs.sh diff --git a/bin/vivado-ubuntu24.04-libs.sh b/bin/vivado-ubuntu24.04-libs.sh new file mode 100755 index 000000000..29a0f1671 --- /dev/null +++ b/bin/vivado-ubuntu24.04-libs.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Rose Thompson rose@rosethompson.net +# Oct 29, 2024 +# Downloads libncurses5 and libtinfo5 from ubuntu 22.04, extracts the libraries and installs to the system. Requires root. + +# 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. + +TmpDir=$(mktemp -d ) +echo $TmpDir + +cd $TmpDir + +wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb +wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.1_amd64.deb + +dpkg-deb -xv libtinfo5_6.3-2ubuntu0.1_amd64.deb ./libtinfo5 +dpkg-deb -xv libncurses5_6.3-2ubuntu0.1_amd64.deb ./libncurses5 + +echo "Installing libraries." +sudo cp libncurses5/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ +sudo cp libncurses5/usr/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ +sudo cp libtinfo5/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ +sudo cp libtinfo5/usr/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ +sudo cp -r libtinfo5/usr/share/doc/* /usr/share/doc/ +sudo ln -f -s /usr/share/doc/libtinfo5/ /usr/share/doc/libncurses5 + +cd - + +echo "Removing temporary files." +rm -rf $TmpDir + +echo "Finished." + + + From b667581ffabd2d73e117f037147c53b915c6e02e Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 29 Oct 2024 17:50:36 -0500 Subject: [PATCH 07/42] Refactored SPI peripheral based on SPI controller module. Works in tests/custom/spitest. --- src/uncore/spi_apb.sv | 707 ++++++++++++++--------------------- src/uncore/spi_controller.sv | 123 +++--- 2 files changed, 335 insertions(+), 495 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 54a072ac9..ebe0726c1 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -30,438 +30,305 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module spi_apb import cvw::*; #(parameter cvw_t P) ( - input logic PCLK, PRESETn, - input logic PSEL, - input logic [7:0] PADDR, - input logic [P.XLEN-1:0] PWDATA, - input logic [P.XLEN/8-1:0] PSTRB, - input logic PWRITE, - input logic PENABLE, - output logic PREADY, - output logic [P.XLEN-1:0] PRDATA, - output logic SPIOut, - input logic SPIIn, - output logic [3:0] SPICS, - output logic SPIIntr, - output logic SPICLK + input logic PCLK, PRESETn, + input logic PSEL, + input logic [7:0] PADDR, + input logic [P.XLEN-1:0] PWDATA, + input logic [P.XLEN/8-1:0] PSTRB, + input logic PWRITE, + input logic PENABLE, + output logic PREADY, + output logic [P.XLEN-1:0] PRDATA, + output logic SPIOut, + input logic SPIIn, + output logic [3:0] SPICS, + output logic SPIIntr, + output logic SPICLK ); // register map - localparam SPI_SCKDIV = 8'h00; - localparam SPI_SCKMODE = 8'h04; - localparam SPI_CSID = 8'h10; - localparam SPI_CSDEF = 8'h14; - localparam SPI_CSMODE = 8'h18; - localparam SPI_DELAY0 = 8'h28; - localparam SPI_DELAY1 = 8'h2C; - localparam SPI_FMT = 8'h40; - localparam SPI_TXDATA = 8'h48; - localparam SPI_RXDATA = 8'h4C; - localparam SPI_TXMARK = 8'h50; - localparam SPI_RXMARK = 8'h54; - localparam SPI_IE = 8'h70; - localparam SPI_IP = 8'h74; - - // receive shift register states - typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} rsrstatetype; - - - // SPI control registers. Refer to SiFive FU540-C000 manual - logic [11:0] SckDiv; - logic [1:0] SckMode; - logic [1:0] ChipSelectID; - logic [3:0] ChipSelectDef; - logic [1:0] ChipSelectMode; - logic [15:0] Delay0, Delay1; - logic [4:0] Format; - logic [7:0] ReceiveData; - logic [2:0] TransmitWatermark, ReceiveWatermark; - logic [8:0] TransmitData; - logic [1:0] InterruptEnable, InterruptPending; - - // Bus interface signals - logic [7:0] Entry; - logic Memwrite; - logic [31:0] Din, Dout; - logic TransmitInactive; // High when there is no transmission, used as hardware interlock signal - - // FIFO FSM signals - // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] - logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; - logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; - logic TransmitFIFOWriteIncrement; - logic ReceiveFiFoWriteInc; - logic ReceiveFIFOReadIncrement; - logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; - logic [7:0] TransmitFIFOReadData; - /* verilator lint_off UNDRIVEN */ - logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs - /* verilator lint_off UNDRIVEN */ - logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission) - rsrstatetype ReceiveState; - logic ReceiveFiFoTakingData; - - // Transmission signals - logic ZeroDiv; // High when SckDiv is 0 - logic [11:0] DivCounter; // Counter for sck - logic SCLKenable; // Flip flop enable high every sclk edge - - // Delay signals - logic [8:0] ImplicitDelay1; // Adds implicit delay to cs-sck delay counter based on phase - logic [8:0] ImplicitDelay2; // Adds implicit delay to sck-cs delay counter based on phase - logic [8:0] CS_SCKCount; // Counter for cs-sck delay - logic [8:0] SCK_CSCount; // Counter for sck-cs delay - logic [8:0] InterCSCount; // Counter for inter cs delay - logic [8:0] InterXFRCount; // Counter for inter xfr delay - logic ZeroDelayHoldMode; // High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0 - - // Frame counting signals - logic FirstFrame; - logic [3:0] FrameCount; // Counter for number of frames in transmission - logic ReceivePenultimateFrame; // High when penultimate frame in transmission has been reached - - // State fsm signals - logic Active; // High when state is either Active1 or Active0 (during transmission) - logic Active0; // High when state is Active0 - - // Shift reg signals - logic ShiftEdge; // Determines which edge of sck to shift from TransmitShiftReg - logic [7:0] TransmitShiftReg; // Transmit shift register - logic [7:0] ReceiveShiftReg; // Receive shift register - logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg - logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB - logic TransmitShiftRegLoad; // Determines when to load TransmitShiftReg - logic TransmitShiftRegLoadSingleCycle; // Version of TransmitShiftRegLoad which is only high for a single SCLK cycle to prevent double loads - logic TransmitShiftRegLoadDelay; // TransmitShiftRegLoad delayed by an SCLK cycle, inverted and anded with TransmitShiftRegLoad to create a single cycle signal - logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read - logic ReceiveShiftFull; // High when receive shift register is full - logic TransmitShiftEmpty; // High when transmit shift register is empty - logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) - logic [3:0] LeftShiftAmount; // Determines left shift amount to left-align data when little endian - logic [7:0] ASR; // AlignedReceiveShiftReg - logic ShiftEdgeSPICLK; // Changes ShiftEdge when SckDiv is 0 - - // CS signals - logic [3:0] ChipSelectAuto; // Assigns ChipSelect value to selected CS signal based on CS ID - logic [3:0] ChipSelectInternal; // Defines what each ChipSelect signal should be based on transmission status and ChipSelectDef - logic DelayMode; // Determines where to place implicit half cycle delay based on sck phase for CS assertion - - // Miscellaneous signals delayed/early by 1 PCLK cycle - logic ReceiveShiftFullDelay; // Delays ReceiveShiftFull signal by 1 PCLK cycle - logic ReceiveShiftFullDelayPCLK; // ReceiveShiftFull delayed by 1 PCLK cycle - logic TransmitFIFOReadEmptyDelay; - logic SCLKenableEarly; // SCLKenable 1 PCLK cycle early, needed for on time register changes when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0 - - - - // APB access - assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses - assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase - assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP | TransmitInactive; // Tie PREADY to transmission for hardware interlock - - // Account for subword read/write circuitry - // -- Note SPI registers are 32 bits no matter what; access them with LW SW. - - assign Din = PWDATA[31:0]; - if (P.XLEN == 64) assign PRDATA = { Dout, Dout}; - else assign PRDATA = Dout; - - // Register access - always_ff@(posedge PCLK) - if (~PRESETn) begin - SckDiv <= 12'd3; - SckMode <= 2'b0; - ChipSelectID <= 2'b0; - ChipSelectDef <= 4'b1111; - ChipSelectMode <= 2'b0; - Delay0 <= {8'b1,8'b1}; - Delay1 <= {8'b0,8'b1}; - Format <= {5'b10000}; - TransmitData <= 9'b0; - TransmitWatermark <= 3'b0; - ReceiveWatermark <= 3'b0; - InterruptEnable <= 2'b0; - InterruptPending <= 2'b0; - end else begin // writes - - - /* verilator lint_off CASEINCOMPLETE */ - if (Memwrite & TransmitInactive) - case(Entry) // flop to sample inputs - SPI_SCKDIV: SckDiv <= Din[11:0]; - SPI_SCKMODE: SckMode <= Din[1:0]; - SPI_CSID: ChipSelectID <= Din[1:0]; - SPI_CSDEF: ChipSelectDef <= Din[3:0]; - SPI_CSMODE: ChipSelectMode <= Din[1:0]; - SPI_DELAY0: Delay0 <= {Din[23:16], Din[7:0]}; - SPI_DELAY1: Delay1 <= {Din[23:16], Din[7:0]}; - SPI_FMT: Format <= {Din[19:16], Din[2]}; - SPI_TXMARK: TransmitWatermark <= Din[2:0]; - SPI_RXMARK: ReceiveWatermark <= Din[2:0]; - SPI_IE: InterruptEnable <= Din[1:0]; - endcase - - if (Memwrite) - case(Entry) - SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0]; - endcase - /* verilator lint_off CASEINCOMPLETE */ - - // According to FU540 spec: Once interrupt is pending, it will remain set until number - // of entries in tx/rx fifo is strictly more/less than tx/rxmark - InterruptPending[0] <= TransmitReadMark; - InterruptPending[1] <= RecieveWriteMark; - - case(Entry) // Flop to sample inputs - SPI_SCKDIV: Dout <= {20'b0, SckDiv}; - SPI_SCKMODE: Dout <= {30'b0, SckMode}; - SPI_CSID: Dout <= {30'b0, ChipSelectID}; - SPI_CSDEF: Dout <= {28'b0, ChipSelectDef}; - SPI_CSMODE: Dout <= {30'b0, ChipSelectMode}; - SPI_DELAY0: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]}; - SPI_DELAY1: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]}; - SPI_FMT: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0}; - SPI_TXDATA: Dout <= {TransmitFIFOWriteFull, 23'b0, 8'b0}; - SPI_RXDATA: Dout <= {ReceiveFIFOReadEmpty, 23'b0, ReceiveData[7:0]}; - SPI_TXMARK: Dout <= {29'b0, TransmitWatermark}; - SPI_RXMARK: Dout <= {29'b0, ReceiveWatermark}; - SPI_IE: Dout <= {30'b0, InterruptEnable}; - SPI_IP: Dout <= {30'b0, InterruptPending}; - default: Dout <= 32'b0; - endcase - end - - // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) - // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv - // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase - // When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). SCLKenableEarly doesn't work right for SckDiv=0 - assign ZeroDiv = ~|(SckDiv[10:0]); - assign SCLKenable = ZeroDiv ? 1 : (DivCounter == SckDiv); - assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv); - always_ff @(posedge PCLK) - if (~PRESETn) DivCounter <= '0; - else if (SCLKenable) DivCounter <= 12'b0; - else DivCounter <= DivCounter + 12'b1; - - // Asserts when transmission is one frame before complete - assign ReceivePenultimateFrame = ((FrameCount + 4'b0001) == Format[4:1]); - assign FirstFrame = (FrameCount == 4'b0); - - // Computing delays - // When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs - assign ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1; - assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0; - - // Calculate when tx/rx shift registers are full/empty - - // Transmit Shift FSM - always_ff @(posedge PCLK) - if (~PRESETn) TransmitShiftEmpty <= 1'b1; - else if (TransmitShiftEmpty) begin - if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrame & Active0))) TransmitShiftEmpty <= 1'b1; - else if (~TransmitFIFOReadEmpty) TransmitShiftEmpty <= 1'b0; - end else begin - if (ReceivePenultimateFrame & Active0) TransmitShiftEmpty <= 1'b1; - else TransmitShiftEmpty <= 1'b0; - end - - // Receive Shift FSM - always_ff @(posedge PCLK) - if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState; - else if (SCLKenable) begin - case (ReceiveState) - ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState; - ReceiveShiftNotFullState: if (ReceivePenultimateFrame & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState; - else ReceiveState <= ReceiveShiftNotFullState; - ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState; - endcase - end - - assign ReceiveShiftFull = SckMode[0] ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState); - - // Calculate tx/rx fifo write and recieve increment signals - - always_ff @(posedge PCLK) - if (~PRESETn) TransmitFIFOWriteIncrement <= 1'b0; - else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); - - always_ff @(posedge PCLK) - if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0; - else ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); - - assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty)); - - always_ff @(posedge PCLK) - if (~PRESETn) TransmitShiftRegLoadDelay <=0; - else if (SCLKenable) TransmitShiftRegLoadDelay <= TransmitShiftRegLoad; - assign TransmitShiftRegLoadSingleCycle = TransmitShiftRegLoad & ~TransmitShiftRegLoadDelay; - always_ff @(posedge PCLK) - if (~PRESETn) TransmitFIFOReadIncrement <= 0; - else if (SCLKenable) TransmitFIFOReadIncrement <= TransmitShiftRegLoadSingleCycle; - // Tx/Rx FIFOs - spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], - TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark); - spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveFiFoWriteInc, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, - ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark); - - always_ff @(posedge PCLK) - if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1'b1; - else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty; - - always_ff @(posedge PCLK) - if (~PRESETn) ReceiveShiftFullDelay <= 1'b0; - else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull; - - assign ReceiveFiFoTakingData = ReceiveFiFoWriteInc & ~ReceiveFIFOWriteFull; + localparam SPI_SCKDIV = 8'h00; + localparam SPI_SCKMODE = 8'h04; + localparam SPI_CSID = 8'h10; + localparam SPI_CSDEF = 8'h14; + localparam SPI_CSMODE = 8'h18; + localparam SPI_DELAY0 = 8'h28; + localparam SPI_DELAY1 = 8'h2C; + localparam SPI_FMT = 8'h40; + localparam SPI_TXDATA = 8'h48; + localparam SPI_RXDATA = 8'h4C; + localparam SPI_TXMARK = 8'h50; + localparam SPI_RXMARK = 8'h54; + localparam SPI_IE = 8'h70; + localparam SPI_IP = 8'h74; - always_ff @(posedge PCLK) - if (~PRESETn) ReceiveFiFoWriteInc <= 1'b0; - else if (SCLKenable & ReceiveShiftFull) ReceiveFiFoWriteInc <= 1'b1; - else if (SCLKenable & ReceiveFiFoTakingData) ReceiveFiFoWriteInc <= 1'b0; - always_ff @(posedge PCLK) - if (~PRESETn) ReceiveShiftFullDelayPCLK <= 1'b0; - else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull; + // SPI control registers. Refer to SiFive FU540-C000 manual + logic [11:0] SckDiv; + logic [1:0] SckMode; + logic [1:0] ChipSelectID; + logic [3:0] ChipSelectDef; + logic [1:0] ChipSelectMode; + logic [15:0] Delay0, Delay1; + logic [4:0] Format; + logic [7:0] ReceiveData; + logic [8:0] TransmitData; + logic [2:0] TransmitWatermark, ReceiveWatermark; + logic [1:0] InterruptEnable, InterruptPending; + // Bus interface signals + logic [7:0] Entry; + logic Memwrite; + logic [31:0] Din, Dout; + // SPI Controller signals + logic SCLKenable; + logic EndOfFrame; + logic EndOfFrameDelay; + logic Transmitting; + logic InactiveState; + logic ResetSCLKenable; + logic TransmitStart; - // Main FSM which controls SPI transmission - typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype; - statetype state; + // Transmit Start State Machine Variables + typedef enum logic [1:0] {READY, START, WAIT} txState; + txState CurrState, NextState; + + // FIFO FSM signals + // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] + logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; + logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; + logic TransmitFIFOWriteIncrement; + logic [7:0] TransmitFIFOReadData; - always_ff @(posedge PCLK) - if (~PRESETn) begin - state <= CS_INACTIVE; - FrameCount <= 4'b0; - SPICLK <= SckMode[1]; - end else if (SCLKenable) begin + logic ReceiveFIFOWriteInc; + logic ReceiveFIFOReadIncrement; + logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; + + /* verilator lint_off UNDRIVEN */ + logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs + /* verilator lint_off UNDRIVEN */ + logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission) + + // Shift reg signals + logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg + logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg + logic [7:0] TransmitReg; // Transmit shift register + logic [7:0] ReceiveShiftReg; // Receive shift register + logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB + logic TransmitLoad; // Determines when to load TransmitReg + logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + + // Shift stuff due to Format register? + logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) + logic [3:0] LeftShiftAmount; // Determines left shift amount to left-align data when little endian + logic [7:0] ASR; // AlignedReceiveShiftReg + + // CS signals + logic [3:0] ChipSelectAuto; // Assigns ChipSelect value to selected CS signal based on CS ID + logic [3:0] ChipSelectInternal; // Defines what each ChipSelect signal should be based on transmission status and ChipSelectDef + + // APB access + assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses + assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase + // assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP; + assign PREADY = 1'b1; + + // Account for subword read/write circuitry + // -- Note SPI registers are 32 bits no matter what; access them with LW SW. + + assign Din = PWDATA[31:0]; + if (P.XLEN == 64) assign PRDATA = { Dout, Dout}; + else assign PRDATA = Dout; + + // Register access + always_ff@(posedge PCLK) + if (~PRESETn) begin + SckDiv <= 12'd3; + SckMode <= 2'b0; + ChipSelectID <= 2'b0; + ChipSelectDef <= 4'b1111; + ChipSelectMode <= 2'b0; + Delay0 <= {8'b1,8'b1}; + Delay1 <= {8'b0,8'b1}; + Format <= {5'b10000}; + TransmitData <= 9'b0; + TransmitWatermark <= 3'b0; + ReceiveWatermark <= 3'b0; + InterruptEnable <= 2'b0; + InterruptPending <= 2'b0; + end else begin // writes /* verilator lint_off CASEINCOMPLETE */ - case (state) - CS_INACTIVE: begin - CS_SCKCount <= 9'b1; - SCK_CSCount <= 9'b10; - FrameCount <= 4'b0; - InterCSCount <= 9'b10; - InterXFRCount <= 9'b1; - if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0; - else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) begin - state <= ACTIVE_0; - SPICLK <= ~SckMode[1]; - end else SPICLK <= SckMode[1]; - end - DELAY_0: begin - CS_SCKCount <= CS_SCKCount + 9'b1; - if (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1)) begin - state <= ACTIVE_0; - SPICLK <= ~SckMode[1]; - end - end - ACTIVE_0: begin - FrameCount <= FrameCount + 4'b1; - SPICLK <= SckMode[1]; - state <= ACTIVE_1; - end - ACTIVE_1: begin - InterXFRCount <= 9'b1; - if (FrameCount < Format[4:1]) begin - state <= ACTIVE_0; - SPICLK <= ~SckMode[1]; - end - else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin - state <= ACTIVE_0; - SPICLK <= ~SckMode[1]; - CS_SCKCount <= 9'b1; - SCK_CSCount <= 9'b10; - FrameCount <= 4'b0; - InterCSCount <= 9'b10; - end - else if (ChipSelectMode[1:0] == 2'b10) state <= INTER_XFR; - else if (~|(Delay0[15:8]) & (~SckMode[0])) state <= INTER_CS; - else state <= DELAY_1; - end - DELAY_1: begin - SCK_CSCount <= SCK_CSCount + 9'b1; - if (SCK_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2)) state <= INTER_CS; - end - INTER_CS: begin - InterCSCount <= InterCSCount + 9'b1; - SPICLK <= SckMode[1]; - if (InterCSCount >= ({Delay1[7:0],1'b0})) state <= CS_INACTIVE; - end - INTER_XFR: begin - CS_SCKCount <= 9'b1; - SCK_CSCount <= 9'b10; - FrameCount <= 4'b0; - InterCSCount <= 9'b10; - InterXFRCount <= InterXFRCount + 9'b1; - if ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & (~TransmitFIFOReadEmptyDelay | ~TransmitShiftEmpty)) begin - state <= ACTIVE_0; - SPICLK <= ~SckMode[1]; - end else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE; - else SPICLK <= SckMode[1]; - end - endcase - /* verilator lint_off CASEINCOMPLETE */ - end - - - - 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 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]))); - assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode) | ((state == ACTIVE_1) & ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty) & (FrameCount == Format[4:1])))); - assign Active0 = (state == ACTIVE_0); - assign ShiftEdgeSPICLK = ZeroDiv ? ~SPICLK : SPICLK; - - // Signal tracks which edge of sck to shift data - always_comb - case(SckMode[1:0]) - 2'b00: ShiftEdge = ShiftEdgeSPICLK & SCLKenable; - 2'b01: ShiftEdge = (~ShiftEdgeSPICLK & ~FirstFrame & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive); - 2'b10: ShiftEdge = ~ShiftEdgeSPICLK & SCLKenable; - 2'b11: ShiftEdge = (ShiftEdgeSPICLK & ~FirstFrame & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive); - default: ShiftEdge = ShiftEdgeSPICLK & SCLKenable; + if (Memwrite) + case(Entry) // flop to sample inputs + SPI_SCKDIV: SckDiv <= Din[11:0]; + SPI_SCKMODE: SckMode <= Din[1:0]; + SPI_CSID: ChipSelectID <= Din[1:0]; + SPI_CSDEF: ChipSelectDef <= Din[3:0]; + SPI_CSMODE: ChipSelectMode <= Din[1:0]; + SPI_DELAY0: Delay0 <= {Din[23:16], Din[7:0]}; + SPI_DELAY1: Delay1 <= {Din[23:16], Din[7:0]}; + SPI_FMT: Format <= {Din[19:16], Din[2]}; + SPI_TXMARK: TransmitWatermark <= Din[2:0]; + SPI_RXMARK: ReceiveWatermark <= Din[2:0]; + SPI_IE: InterruptEnable <= Din[1:0]; 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; - else if (TransmitShiftRegLoadSingleCycle) TransmitShiftReg <= TransmitDataEndian; - else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], TransmitShiftReg[0]}; - - assign SPIOut = TransmitShiftReg[7]; - - // If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn - // There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges - assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn; - - // Receive shift register - always_ff @(posedge PCLK) - if(~PRESETn) ReceiveShiftReg <= 8'b0; - else if (SampleEdge & SCLKenable) begin - if (~Active) ReceiveShiftReg <= 8'b0; - else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; - end - - // Aligns received data and reverses if little-endian - assign LeftShiftAmount = 4'h8 - Format[4:1]; - assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0]; - assign ReceiveShiftRegEndian = Format[0] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0]; - - // Interrupt logic: raise interrupt if any enabled interrupts are pending - assign SPIIntr = |(InterruptPending & InterruptEnable); - - // Chip select logic - always_comb - case(ChipSelectID[1:0]) - 2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]}; - 2'b01: ChipSelectAuto = {ChipSelectDef[3],ChipSelectDef[2], ChipSelectInternal[1], ChipSelectDef[0]}; - 2'b10: ChipSelectAuto = {ChipSelectDef[3],ChipSelectInternal[2], ChipSelectDef[1], ChipSelectDef[0]}; - 2'b11: ChipSelectAuto = {ChipSelectInternal[3],ChipSelectDef[2], ChipSelectDef[1], ChipSelectDef[0]}; + if (Memwrite) + case(Entry) + SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0]; endcase + /* verilator lint_off CASEINCOMPLETE */ + + // According to FU540 spec: Once interrupt is pending, it will remain set until number + // of entries in tx/rx fifo is strictly more/less than tx/rxmark + InterruptPending[0] <= TransmitReadMark; + InterruptPending[1] <= RecieveWriteMark; + + case(Entry) // Flop to sample inputs + SPI_SCKDIV: Dout <= {20'b0, SckDiv}; + SPI_SCKMODE: Dout <= {30'b0, SckMode}; + SPI_CSID: Dout <= {30'b0, ChipSelectID}; + SPI_CSDEF: Dout <= {28'b0, ChipSelectDef}; + SPI_CSMODE: Dout <= {30'b0, ChipSelectMode}; + SPI_DELAY0: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]}; + SPI_DELAY1: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]}; + SPI_FMT: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0}; + SPI_TXDATA: Dout <= {TransmitFIFOWriteFull, 23'b0, 8'b0}; + SPI_RXDATA: Dout <= {ReceiveFIFOReadEmpty, 23'b0, ReceiveData[7:0]}; + SPI_TXMARK: Dout <= {29'b0, TransmitWatermark}; + SPI_RXMARK: Dout <= {29'b0, ReceiveWatermark}; + SPI_IE: Dout <= {30'b0, InterruptEnable}; + SPI_IP: Dout <= {30'b0, InterruptPending}; + default: Dout <= 32'b0; + endcase + end - assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto; + // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) + // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv + // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase + // When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). + + // SPI Controller module ------------------------------------------- + // This module controls state and timing signals that drive the rest of this module + assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV); + + spi_controller controller(PCLK, PRESETn, + // Transmit Signals + TransmitStart, ResetSCLKenable, + // Register Inputs + SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, + // txFIFO stuff + TransmitFIFOReadEmpty, + // Timing + SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, EndOfFrameDelay, + // State stuff + Transmitting, InactiveState, + // Outputs + SPICLK); + + // Transmit FIFO --------------------------------------------------- + always_ff @(posedge PCLK) + if (~PRESETn) begin + TransmitFIFOWriteIncrement <= 1'b0; + TransmitFIFOReadIncrement <= 1'b0; + end else begin + TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); + TransmitFIFOReadIncrement <= TransmitLoad; + end + + // Setup TransmitStart state machine + always_ff @(posedge PCLK) begin + if (~PRESETn) begin + CurrState <= READY; + end else if (SCLKenable) begin + CurrState <= NextState; + end + end + + // State machine for starting transmissions + always_comb begin + case (CurrState) + READY: if (~TransmitFIFOReadEmpty) NextState = START; + else NextState = READY; + START: NextState = WAIT; + WAIT: if (TransmitFIFOReadEmpty & ~Transmitting) NextState = READY; + else NextState = WAIT; + endcase + end + + assign TransmitStart = (CurrState == START); + + spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, + TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, + TransmitData[7:0], + TransmitWriteWatermarkLevel, TransmitWatermark[2:0], + TransmitFIFOReadData[7:0], + TransmitFIFOWriteFull, + TransmitFIFOReadEmpty, + TransmitWriteMark, TransmitReadMark); + + + // Receive FIFO ---------------------------------------------------- + always_ff @(posedge PCLK) + if (~PRESETn) begin + ReceiveFIFOReadIncrement <= 1'b0; + ReceiveFIFOWriteInc <= 1'b0; + end else begin + ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); + ReceiveFIFOWriteInc <= EndOfFrameDelay; + end + + spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, + ReceiveFIFOWriteInc, ReceiveFIFOReadIncrement, + ReceiveShiftRegEndian, ReceiveWatermark[2:0], + ReceiveReadWatermarkLevel, + ReceiveData[7:0], + ReceiveFIFOWriteFull, + ReceiveFIFOReadEmpty, + RecieveWriteMark, RecieveReadMark); + + // Transmit shift register + assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~TransmitFIFOReadEmpty); + assign TransmitDataEndian = Format[0] ? {<<{TransmitFIFOReadData[7:0]}} : TransmitFIFOReadData[7:0]; + always_ff @(posedge PCLK) + if(~PRESETn) TransmitReg <= 8'b0; + else if (TransmitLoad) TransmitReg <= TransmitDataEndian; + else if (ShiftEdge) TransmitReg <= {TransmitReg[6:0], TransmitReg[0]}; + + assign SPIOut = TransmitReg[7]; + + // If in loopback mode, receive shift register is connected directly + // to module's output pins. Else, connected to SPIIn. There are no + // setup/hold time issues because transmit shift register and receive + // shift register always shift/sample on opposite edges + assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn; + + // Receive shift register + always_ff @(posedge PCLK) + if(~PRESETn) ReceiveShiftReg <= 8'b0; + else if (SampleEdge) begin + if (~Transmitting) ReceiveShiftReg <= 8'b0; + else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; + end + + // Aligns received data and reverses if little-endian + assign LeftShiftAmount = 4'h8 - Format[4:1]; + assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0]; + assign ReceiveShiftRegEndian = Format[0] ? {<<{ASR[7:0]}} : ASR[7:0]; + + // Interrupt logic: raise interrupt if any enabled interrupts are pending + assign SPIIntr = |(InterruptPending & InterruptEnable); + + // Chip select logic + assign ChipSelectInternal = InactiveState ? ChipSelectDef : ~ChipSelectDef; + always_comb + case(ChipSelectID[1:0]) + 2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]}; + 2'b01: ChipSelectAuto = {ChipSelectDef[3],ChipSelectDef[2], ChipSelectInternal[1], ChipSelectDef[0]}; + 2'b10: ChipSelectAuto = {ChipSelectDef[3],ChipSelectInternal[2], ChipSelectDef[1], ChipSelectDef[0]}; + 2'b11: ChipSelectAuto = {ChipSelectInternal[3],ChipSelectDef[2], ChipSelectDef[1], ChipSelectDef[0]}; + endcase + assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto; + endmodule diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index c4305047e..9692b7588 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -28,21 +28,33 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// - -module spi_controller ( +module spi_controller ( input logic PCLK, input logic PRESETn, + + // Start Transmission input logic TransmitStart, + input logic ResetSCLKenable, + + // Registers input logic [11:0] SckDiv, input logic [1:0] SckMode, input logic [1:0] CSMode, - input logic [15:0] Delay0, - input logic [15:0] Delay1, - input logic [7:0] txFIFORead, + input logic [15:0] Delay0, + input logic [15:0] Delay1, + + // Is the Transmit FIFO Empty? input logic txFIFOReadEmpty, - output logic SPICLK, - output logic SPIOUT, - output logic CS + + // Control signals + output logic SCLKenable, + output logic ShiftEdge, + output logic SampleEdge, + output logic EndOfFrame, + output logic EndOfFrameDelay, + output logic Transmitting, + output logic InactiveState, + output logic SPICLK ); // CSMode Stuff @@ -55,36 +67,32 @@ module spi_controller ( // SCLKenable stuff logic [11:0] DivCounter; - logic SCLKenable; - logic SCLKenableEarly; - logic SCLKenableLate; - logic EdgeTiming; + // logic SCLKenable; + // logic SCLKenableEarly; logic ZeroDiv; - logic Clock0; - logic Clock1; logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK! // Shift and Sample Edges logic PreShiftEdge; logic PreSampleEdge; - logic ShiftEdge; - logic SampleEdge; + // logic ShiftEdge; + // logic SampleEdge; // Frame stuff logic [2:0] BitNum; logic LastBit; - logic EndOfFrame; - logic EndOfFrameDelay; + //logic EndOfFrame; + //logic EndOfFrameDelay; logic PhaseOneOffset; // Transmit Stuff logic ContinueTransmit; // SPIOUT Stuff - logic TransmitLoad; + // logic TransmitLoad; logic [7:0] TransmitReg; - logic Transmitting; + //logic Transmitting; logic EndTransmission; logic HoldMode; @@ -135,13 +143,9 @@ module spi_controller ( // SampleEdge. This makes sure that SPICLK is an output of a register // and it properly synchronizes signals. - assign SCLKenableLate = DivCounter > SckDiv; assign SCLKenable = DivCounter == SckDiv; - assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; + // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; assign LastBit = BitNum == 3'd7; - assign EdgeTiming = SckDiv > 12'b0 ? SCLKenableEarly : SCLKenable; - - //assign SPICLK = Clock0; assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame; assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay; @@ -196,7 +200,7 @@ module spi_controller ( end // Reset divider - if (SCLKenable | TransmitStart) begin + if (SCLKenable | TransmitStart | ResetSCLKenable) begin DivCounter <= 12'b0; end else begin DivCounter = DivCounter + 12'd1; @@ -242,8 +246,8 @@ module spi_controller ( // typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; // statetype CurrState, NextState; - assign HoldMode = CSMode == 2'b10; - assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); + assign HoldMode = CSMode == HOLDMODE; + // assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -255,61 +259,43 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: begin // INACTIVE case -------------------------------- - if (TransmitStart) begin - if (~HasCSSCK) begin - NextState = TRANSMIT; - end else begin - NextState = CSSCK; - end - end else begin - NextState = INACTIVE; - end - end - CSSCK: begin // DELAY0 case ------------------------------------- - if (EndOfCSSCK) begin - NextState = TRANSMIT; - end - end + INACTIVE: if (TransmitStart) + if (~HasCSSCK) NextState = TRANSMIT; + else NextState = CSSCK; + else NextState = INACTIVE; + CSSCK: if (EndOfCSSCK) NextState = TRANSMIT; + else NextState = CSSCK; TRANSMIT: begin // TRANSMIT case -------------------------------- case(CSMode) AUTOMODE: begin - if (EndTransmission) begin - NextState = INACTIVE; - end else if (ContinueTransmit) begin - NextState = SCKCS; - end + if (EndTransmission) NextState = INACTIVE; + else if (ContinueTransmit) NextState = SCKCS; end HOLDMODE: begin - if (EndTransmission) begin - NextState = HOLD; - end else if (ContinueTransmit) begin - if (HasINTERXFR) NextState = INTERXFR; - end + if (EndTransmission) NextState = HOLD; + else if (ContinueTransmit & HasINTERXFR) NextState = INTERXFR; + else NextState = TRANSMIT; end OFFMODE: begin end - endcase end SCKCS: begin // SCKCS case -------------------------------------- - if (EndOfSCKCS) begin - if (EndTransmission) begin + if (EndOfSCKCS) + if (EndTransmission) if (CSMode == AUTOMODE) NextState = INACTIVE; else if (CSMode == HOLDMODE) NextState = HOLD; - end else if (ContinueTransmit) begin + else if (ContinueTransmit) if (HasINTERCS) NextState = INTERCS; else NextState = TRANSMIT; - end - end end HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin NextState = INACTIVE; end else if (TransmitStart) begin // If FIFO is written to, start again. NextState = TRANSMIT; - end + end else NextState = HOLD; end INTERCS: begin // INTERCS case ---------------------------------- if (EndOfINTERCS) begin @@ -330,19 +316,6 @@ module spi_controller ( assign Transmitting = CurrState == TRANSMIT; assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR); - - // - always_ff @(posedge PCLK) begin - if (~PRESETn) begin - TransmitReg <= 8'b0; - end else if (TransmitLoad) begin - TransmitReg <= txFIFORead; - end else if (ShiftEdge) begin - TransmitReg <= {TransmitReg[6:0], TransmitReg[0]}; - end - end - - assign SPIOUT = TransmitReg[7]; - assign CS = CurrState == INACTIVE | CurrState == INTERCS; + assign InactiveState = CurrState == INACTIVE | CurrState == INTERCS; endmodule From 57d1709582726e66c5c6dbd645e6e8e4e2e06f33 Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Wed, 30 Oct 2024 16:01:11 -0500 Subject: [PATCH 08/42] The path to the zsbl was wrong all this time, but for reason was working with older versions of Ubuntu, but one 24.04 it causes vivado to not find the rom and ram. --- fpga/constraints/marked_debug.txt | 19 +++++++++++++++++++ fpga/constraints/small-debug-spi.xdc | 1 - fpga/generator/Makefile | 4 ++-- fpga/generator/wally.tcl | 3 ++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/fpga/constraints/marked_debug.txt b/fpga/constraints/marked_debug.txt index 1d23c29a2..a50091827 100644 --- a/fpga/constraints/marked_debug.txt +++ b/fpga/constraints/marked_debug.txt @@ -5,3 +5,22 @@ wally/wallypipelinedcore.sv: logic InstrM lsu/lsu.sv: logic IEUAdrM lsu/lsu.sv: logic MemRWM mmu/hptw.sv: logic SATP_REGW +uncore/spi_apb.sv: logic ShiftIn +uncore/spi_apb.sv: logic ReceiveShiftReg +uncore/spi_apb.sv: logic SCLKenable +uncore/spi_apb.sv: logic SampleEdge +uncore/spi_apb.sv: logic Active +uncore/spi_apb.sv: statetype state +uncore/spi_apb.sv: typedef rsrstatetype +uncore/spi_apb.sv: logic SPICLK +uncore/spi_apb.sv: logic SPIOut +uncore/spi_apb.sv: logic SPICS +uncore/spi_apb.sv: logic SckMode +uncore/spi_apb.sv: logic SckDiv +uncore/spi_apb.sv: logic ShiftEdge +uncore/spi_apb.sv: logic TransmitShiftRegLoad +uncore/spi_apb.sv: logic TransmitShiftReg +uncore/spi_apb.sv: logic TransmitData +uncore/spi_apb.sv: logic ReceiveData +uncore/spi_apb.sv: logic ReceiveShiftRegEndian +uncore/spi_apb.sv: logic ASR diff --git a/fpga/constraints/small-debug-spi.xdc b/fpga/constraints/small-debug-spi.xdc index f62e3d4d3..5951bdcb8 100644 --- a/fpga/constraints/small-debug-spi.xdc +++ b/fpga/constraints/small-debug-spi.xdc @@ -191,7 +191,6 @@ set_property port_width 1 [get_debug_ports u_ila_0/probe33] set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe33] connect_debug_port u_ila_0/probe33 [get_nets [list {wallypipelinedsoc/uncoregen.uncore/sdc.sdc/TransmitFIFOReadEmpty} ]] - # 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/generator/Makefile b/fpga/generator/Makefile index 7ffd9f163..52e46ec38 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -69,8 +69,8 @@ PreProcessFiles: ./insert_debug_comment.sh # 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 + 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 # build the Zero stage boot loader (ZSBL) .PHONY: zsbl diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index 3ca0c3360..7935b5913 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -102,7 +102,8 @@ if {$board=="ArtyA7"} { } else { #source ../constraints/vcu-small-debug.xdc #source ../constraints/small-debug.xdc - source ../constraints/small-debug-spi.xdc + #source ../constraints/small-debug.xdc + source ../constraints/big-debug-spi.xdc } From 1629eda6088fd3d4f916f6aed288941eaaeb144f Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Wed, 30 Oct 2024 16:07:05 -0500 Subject: [PATCH 09/42] Added btbthrash to tests.vh. --- testbench/tests.vh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testbench/tests.vh b/testbench/tests.vh index bef41ef22..2b8d3a2ec 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -72,7 +72,8 @@ string coverage64gc[] = '{ "pmpcfg2", "pmppriority", "pmpcbo", - "pmpadrdecs" + "pmpadrdecs", + "btbthrash" }; string buildroot[] = '{ From 4f0723f23618509255922671127d1eba00769c53 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 30 Oct 2024 16:19:46 -0500 Subject: [PATCH 10/42] Fixed enabling of TransmitFIFOReadIncrement and ReceiveFIFOWriteIncrement --- src/uncore/spi_apb.sv | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index ebe0726c1..8442cd1b7 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -231,17 +231,22 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( always_ff @(posedge PCLK) if (~PRESETn) begin TransmitFIFOWriteIncrement <= 1'b0; - TransmitFIFOReadIncrement <= 1'b0; end else begin TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); - TransmitFIFOReadIncrement <= TransmitLoad; end + always_ff @(posedge PCLK) + if (~PRESETn) begin + TransmitFIFOReadIncrement <= 1'b0; + end else if (SCLKenable) begin + TransmitFIFOReadIncrement <= TransmitLoad; + end + // Setup TransmitStart state machine always_ff @(posedge PCLK) begin if (~PRESETn) begin CurrState <= READY; - end else if (SCLKenable) begin + end else begin CurrState <= NextState; end end @@ -273,9 +278,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( always_ff @(posedge PCLK) if (~PRESETn) begin ReceiveFIFOReadIncrement <= 1'b0; - ReceiveFIFOWriteInc <= 1'b0; end else begin ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); + end + + always_ff @(posedge PCLK) + if (~PRESETn) begin + ReceiveFIFOWriteInc <= 1'b0; + end else if (SCLKenable) begin ReceiveFIFOWriteInc <= EndOfFrameDelay; end From 9400a2aba419d83c39e62ab0e80daf6292059d9e Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Wed, 30 Oct 2024 17:20:53 -0500 Subject: [PATCH 11/42] Remove vivavdo-ubuntu24.04-04-lib.sh because Jordan found a better solution by symlinking the new libncurses6 and libtinfo6 to the old libraries. --- bin/vivado-ubuntu24.04-libs.sh | 52 ---------------------------------- 1 file changed, 52 deletions(-) delete mode 100755 bin/vivado-ubuntu24.04-libs.sh diff --git a/bin/vivado-ubuntu24.04-libs.sh b/bin/vivado-ubuntu24.04-libs.sh deleted file mode 100755 index 29a0f1671..000000000 --- a/bin/vivado-ubuntu24.04-libs.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -# Rose Thompson rose@rosethompson.net -# Oct 29, 2024 -# Downloads libncurses5 and libtinfo5 from ubuntu 22.04, extracts the libraries and installs to the system. Requires root. - -# 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. - -TmpDir=$(mktemp -d ) -echo $TmpDir - -cd $TmpDir - -wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb -wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.1_amd64.deb - -dpkg-deb -xv libtinfo5_6.3-2ubuntu0.1_amd64.deb ./libtinfo5 -dpkg-deb -xv libncurses5_6.3-2ubuntu0.1_amd64.deb ./libncurses5 - -echo "Installing libraries." -sudo cp libncurses5/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ -sudo cp libncurses5/usr/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ -sudo cp libtinfo5/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ -sudo cp libtinfo5/usr/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/ -sudo cp -r libtinfo5/usr/share/doc/* /usr/share/doc/ -sudo ln -f -s /usr/share/doc/libtinfo5/ /usr/share/doc/libncurses5 - -cd - - -echo "Removing temporary files." -rm -rf $TmpDir - -echo "Finished." - - - From 4e7e311b26756d724b4531df619bdedca9f716ac Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 30 Oct 2024 18:39:04 -0500 Subject: [PATCH 12/42] Fixed issues relating to SCLKenable and TransmitStart. Works at multiple dividers now, instead of just SckDiv = 0. --- src/uncore/spi_apb.sv | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 8442cd1b7..33978637b 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -89,6 +89,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic ResetSCLKenable; logic TransmitStart; + logic TransmitStartD; // Transmit Start State Machine Variables typedef enum logic [1:0] {READY, START, WAIT} txState; @@ -215,7 +216,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( spi_controller controller(PCLK, PRESETn, // Transmit Signals - TransmitStart, ResetSCLKenable, + TransmitStart, TransmitStartD, ResetSCLKenable, // Register Inputs SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, // txFIFO stuff @@ -239,7 +240,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if (~PRESETn) begin TransmitFIFOReadIncrement <= 1'b0; end else if (SCLKenable) begin - TransmitFIFOReadIncrement <= TransmitLoad; + TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; end // Setup TransmitStart state machine @@ -254,7 +255,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // State machine for starting transmissions always_comb begin case (CurrState) - READY: if (~TransmitFIFOReadEmpty) NextState = START; + READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; WAIT: if (TransmitFIFOReadEmpty & ~Transmitting) NextState = READY; @@ -263,6 +264,10 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( end assign TransmitStart = (CurrState == START); + always_ff @(posedge PCLK) + if (~PRESETn) TransmitStartD <= 1'b0; + else if (TransmitStart) TransmitStartD <= 1'b1; + else if (SCLKenable) TransmitStartD <= 1'b0; spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, From 35c9fe764803e6d3d905b19e2c7e9fc158b88f1c Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 30 Oct 2024 18:45:54 -0500 Subject: [PATCH 13/42] Added changed SPI controller module. New signal TransmitStartD that starts the FSM based on SCLKenable. TransmitStart is responsible for resetting SCLKenable and loading the Transmit Shift Register. --- src/uncore/spi_controller.sv | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 9692b7588..d3c800102 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -34,7 +34,8 @@ module spi_controller ( // Start Transmission input logic TransmitStart, - input logic ResetSCLKenable, + input logic TransmitStartD, + input logic ResetSCLKenable, // Registers input logic [11:0] SckDiv, @@ -168,25 +169,25 @@ module spi_controller ( SCK <= ~SCK; end - if ((CurrState == CSSCK) & SCK) begin + if ((CurrState == CSSCK) & SCK & SCLKenable) begin CSSCKCounter <= CSSCKCounter + 8'd1; - end else begin + end else if (SCLKenable) begin CSSCKCounter <= 8'd0; end - if ((CurrState == SCKCS) & SCK) begin + if ((CurrState == SCKCS) & SCK & SCLKenable) begin SCKCSCounter <= SCKCSCounter + 8'd1; - end else begin + end else if (SCLKenable) begin SCKCSCounter <= 8'd0; end - if ((CurrState == INTERCS) & SCK) begin + if ((CurrState == INTERCS) & SCK & SCLKenable) begin INTERCSCounter <= INTERCSCounter + 8'd1; end else begin INTERCSCounter <= 8'd0; end - if ((CurrState == INTERXFR) & SCK) begin + if ((CurrState == INTERXFR) & SCK & SCLKenable) begin INTERXFRCounter <= INTERXFRCounter + 8'd1; end else begin INTERXFRCounter <= 8'd0; @@ -259,7 +260,7 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: if (TransmitStart) + INACTIVE: if (TransmitStartD) if (~HasCSSCK) NextState = TRANSMIT; else NextState = CSSCK; else NextState = INACTIVE; @@ -293,7 +294,7 @@ module spi_controller ( HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin NextState = INACTIVE; - end else if (TransmitStart) begin // If FIFO is written to, start again. + end else if (TransmitStartD) begin // If FIFO is written to, start again. NextState = TRANSMIT; end else NextState = HOLD; end From 419030bc331483042c8c85b557d5276b2d5fa74c Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 31 Oct 2024 10:41:38 -0500 Subject: [PATCH 14/42] Fixed FSM to continue transmitting after delay. --- src/uncore/spi_controller.sv | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index d3c800102..10ff511a6 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -148,7 +148,8 @@ module spi_controller ( // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; assign LastBit = BitNum == 3'd7; - assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame; + //assign EndOfFrame = SCLKenable & LastBit & Transmitting; + assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay; assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay; always_ff @(posedge PCLK) begin @@ -183,13 +184,13 @@ module spi_controller ( if ((CurrState == INTERCS) & SCK & SCLKenable) begin INTERCSCounter <= INTERCSCounter + 8'd1; - end else begin + end else if (SCLKenable) begin INTERCSCounter <= 8'd0; end if ((CurrState == INTERXFR) & SCK & SCLKenable) begin INTERXFRCounter <= INTERXFRCounter + 8'd1; - end else begin + end else if (SCLKenable) begin INTERXFRCounter <= 8'd0; end @@ -239,7 +240,7 @@ module spi_controller ( end else begin ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : PhaseOneOffset; - SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting; + SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; end end @@ -284,12 +285,13 @@ module spi_controller ( end SCKCS: begin // SCKCS case -------------------------------------- if (EndOfSCKCS) - if (EndTransmission) + if (txFIFOReadEmpty) begin if (CSMode == AUTOMODE) NextState = INACTIVE; else if (CSMode == HOLDMODE) NextState = HOLD; - else if (ContinueTransmit) + end else if (~txFIFOReadEmpty) begin if (HasINTERCS) NextState = INTERCS; else NextState = TRANSMIT; + end end HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin From 72a854eb075f90fde3fa9bfb6ba653845c2d54f6 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 31 Oct 2024 13:01:25 -0500 Subject: [PATCH 15/42] Refactored SPI passes regression save for hardware interlock tests. --- src/uncore/spi_apb.sv | 21 ++++++++++++-- src/uncore/spi_controller.sv | 53 +++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 33978637b..c8084de42 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -86,6 +86,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic EndOfFrameDelay; logic Transmitting; logic InactiveState; + logic [3:0] FrameLength; logic ResetSCLKenable; logic TransmitStart; @@ -213,12 +214,13 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // SPI Controller module ------------------------------------------- // This module controls state and timing signals that drive the rest of this module assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV); + assign FrameLength = Format[4:1]; spi_controller controller(PCLK, PRESETn, // Transmit Signals TransmitStart, TransmitStartD, ResetSCLKenable, // Register Inputs - SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, + SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff TransmitFIFOReadEmpty, // Timing @@ -243,6 +245,19 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; end + // Check whether TransmitReg has been loaded. + // We use this signal to prevent returning to the Ready state for TransmitStart + logic TransmitRegLoaded; + always_ff @(posedge PCLK) begin + if (~PRESETn) begin + TransmitRegLoaded <= 1'b0; + end else if (TransmitLoad) begin + TransmitRegLoaded <= 1'b1; + end else if (ShiftEdge | EndOfFrameDelay) begin + TransmitRegLoaded <= 1'b0; + end + end + // Setup TransmitStart state machine always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -251,14 +266,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( CurrState <= NextState; end end - + // State machine for starting transmissions always_comb begin case (CurrState) READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; - WAIT: if (TransmitFIFOReadEmpty & ~Transmitting) NextState = READY; + WAIT: if (TransmitFIFOReadEmpty & ~Transmitting & ~TransmitRegLoaded) NextState = READY; else NextState = WAIT; endcase end diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 10ff511a6..2b74e79c9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -43,6 +43,7 @@ module spi_controller ( input logic [1:0] CSMode, input logic [15:0] Delay0, input logic [15:0] Delay1, + input logic [3:0] FrameLength, // Is the Transmit FIFO Empty? input logic txFIFOReadEmpty, @@ -146,7 +147,7 @@ module spi_controller ( assign SCLKenable = DivCounter == SckDiv; // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; - assign LastBit = BitNum == 3'd7; + assign LastBit = (BitNum == FrameLength - 4'b1); //assign EndOfFrame = SCLKenable & LastBit & Transmitting; assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay; @@ -161,6 +162,10 @@ module spi_controller ( PreShiftEdge <= 0; PreSampleEdge <= 0; EndOfFrame <= 0; + CSSCKCounter <= 0; + SCKCSCounter <= 0; + INTERCSCounter <= 0; + INTERXFRCounter <= 0; end else begin // TODO: Consolidate into one delay counter since none of the // delays happen at the same time? @@ -172,25 +177,25 @@ module spi_controller ( if ((CurrState == CSSCK) & SCK & SCLKenable) begin CSSCKCounter <= CSSCKCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfCSSCK) begin CSSCKCounter <= 8'd0; end if ((CurrState == SCKCS) & SCK & SCLKenable) begin SCKCSCounter <= SCKCSCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfSCKCS) begin SCKCSCounter <= 8'd0; end if ((CurrState == INTERCS) & SCK & SCLKenable) begin INTERCSCounter <= INTERCSCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfINTERCS) begin INTERCSCounter <= 8'd0; end if ((CurrState == INTERXFR) & SCK & SCLKenable) begin INTERXFRCounter <= INTERXFRCounter + 8'd1; - end else if (SCLKenable) begin + end else if (SCLKenable & EndOfINTERXFR) begin INTERXFRCounter <= 8'd0; end @@ -239,7 +244,7 @@ module spi_controller ( EndOfFrameDelay <= 0; end else begin ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; - PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : PhaseOneOffset; + PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; end @@ -251,6 +256,23 @@ module spi_controller ( assign HoldMode = CSMode == HOLDMODE; // assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); + logic ContinueTransmitD; + logic NextEndDelay; + logic CurrentEndDelay; + + assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR; + assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR; + + always_ff @(posedge PCLK) begin + if (~PRESETn) begin + ContinueTransmitD <= 1'b0; + end else if (NextEndDelay & ~CurrentEndDelay) begin + ContinueTransmitD <= ContinueTransmit; + end else if (EndOfSCKCS & SCLKenable) begin + ContinueTransmitD <= 1'b0; + end + end + always_ff @(posedge PCLK) begin if (~PRESETn) begin CurrState <= INACTIVE; @@ -261,17 +283,19 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: if (TransmitStartD) + INACTIVE: if (TransmitStartD) begin if (~HasCSSCK) NextState = TRANSMIT; else NextState = CSSCK; - else NextState = INACTIVE; + end else begin + NextState = INACTIVE; + end CSSCK: if (EndOfCSSCK) NextState = TRANSMIT; else NextState = CSSCK; TRANSMIT: begin // TRANSMIT case -------------------------------- case(CSMode) AUTOMODE: begin if (EndTransmission) NextState = INACTIVE; - else if (ContinueTransmit) NextState = SCKCS; + else if (EndOfFrameDelay) NextState = SCKCS; end HOLDMODE: begin if (EndTransmission) NextState = HOLD; @@ -279,19 +303,22 @@ module spi_controller ( else NextState = TRANSMIT; end OFFMODE: begin - + if (EndTransmission) NextState = INACTIVE; + else if (ContinueTransmit & HasINTERXFR) NextState = INTERXFR; + else NextState = TRANSMIT; end endcase end SCKCS: begin // SCKCS case -------------------------------------- - if (EndOfSCKCS) - if (txFIFOReadEmpty) begin + if (EndOfSCKCS) begin + if (~ContinueTransmitD) begin if (CSMode == AUTOMODE) NextState = INACTIVE; else if (CSMode == HOLDMODE) NextState = HOLD; - end else if (~txFIFOReadEmpty) begin + end else begin if (HasINTERCS) NextState = INTERCS; else NextState = TRANSMIT; end + end end HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin From 3ee5fffe02b3276a40c1eb99863db1ae19424d71 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 31 Oct 2024 13:54:56 -0500 Subject: [PATCH 16/42] Fixing latches. --- src/uncore/spi_apb.sv | 1 + src/uncore/spi_controller.sv | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index c8084de42..911ab3a15 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -275,6 +275,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( START: NextState = WAIT; WAIT: if (TransmitFIFOReadEmpty & ~Transmitting & ~TransmitRegLoaded) NextState = READY; else NextState = WAIT; + default: NextState = READY; endcase end diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 2b74e79c9..10ad09f91 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -296,6 +296,7 @@ module spi_controller ( AUTOMODE: begin if (EndTransmission) NextState = INACTIVE; else if (EndOfFrameDelay) NextState = SCKCS; + else NextState = TRANSMIT; end HOLDMODE: begin if (EndTransmission) NextState = HOLD; @@ -307,6 +308,7 @@ module spi_controller ( else if (ContinueTransmit & HasINTERXFR) NextState = INTERXFR; else NextState = TRANSMIT; end + default: NextState = TRANSMIT; endcase end SCKCS: begin // SCKCS case -------------------------------------- @@ -318,6 +320,8 @@ module spi_controller ( if (HasINTERCS) NextState = INTERCS; else NextState = TRANSMIT; end + end else begin + NextState = SCKCS; end end HOLD: begin // HOLD mode case ----------------------------------- @@ -331,11 +335,15 @@ module spi_controller ( if (EndOfINTERCS) begin if (HasCSSCK) NextState = CSSCK; else NextState = TRANSMIT; + end else begin + NextState = INTERCS; end end INTERXFR: begin // INTERXFR case -------------------------------- if (EndOfINTERXFR) begin NextState = TRANSMIT; + end else begin + NextState = INTERXFR; end end default: begin From 56a6ad3376276ece7ca22ae3979346b43d20babf Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 31 Oct 2024 15:56:16 -0500 Subject: [PATCH 17/42] Fixed lint issues. --- src/uncore/spi_apb.sv | 5 +++-- src/uncore/spi_controller.sv | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 911ab3a15..5d3352154 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -337,8 +337,9 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Receive shift register always_ff @(posedge PCLK) - if(~PRESETn) ReceiveShiftReg <= 8'b0; - else if (SampleEdge) begin + if(~PRESETn) begin + ReceiveShiftReg <= 8'b0; + end else if (SampleEdge) begin if (~Transmitting) ReceiveShiftReg <= 8'b0; else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; end diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 10ad09f91..605685b4b 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -82,7 +82,7 @@ module spi_controller ( // logic SampleEdge; // Frame stuff - logic [2:0] BitNum; + logic [3:0] BitNum; logic LastBit; //logic EndOfFrame; //logic EndOfFrameDelay; @@ -158,7 +158,7 @@ module spi_controller ( DivCounter <= 12'b0; SPICLK <= SckMode[1]; SCK <= 0; - BitNum <= 3'h0; + BitNum <= 4'h0; PreShiftEdge <= 0; PreSampleEdge <= 0; EndOfFrame <= 0; @@ -210,7 +210,7 @@ module spi_controller ( if (SCLKenable | TransmitStart | ResetSCLKenable) begin DivCounter <= 12'b0; end else begin - DivCounter = DivCounter + 12'd1; + DivCounter <= DivCounter + 12'd1; end // EndOfFrame controller @@ -226,9 +226,9 @@ module spi_controller ( // Increment BitNum if (ShiftEdge & Transmitting) begin - BitNum <= BitNum + 3'd1; + BitNum <= BitNum + 4'd1; end else if (EndOfFrameDelay) begin - BitNum <= 3'b0; + BitNum <= 4'b0; end end end From 63d3be331ff8371231e017b2f94caa0841aca96c Mon Sep 17 00:00:00 2001 From: slmnemo Date: Thu, 31 Oct 2024 15:39:38 -0700 Subject: [PATCH 18/42] Initial pass of removing pre-done source.sh dependency in nightly build --- bin/nightly_build.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/bin/nightly_build.py b/bin/nightly_build.py index cb8583eef..b675fceca 100755 --- a/bin/nightly_build.py +++ b/bin/nightly_build.py @@ -261,9 +261,6 @@ class TestRunner: cvw = folder.joinpath("cvw") self.logger.info(f"cvw is: {cvw}") - # set the WALLY environmental variable to the new repository - os.environ["WALLY"] = str(cvw) - self.cvw = cvw self.sim_dir = cvw.joinpath("bin") self.base_parent_dir = folder @@ -292,11 +289,11 @@ class TestRunner: output_file = self.log_dir.joinpath(f"make-{target}-output.log") else: output_file = self.log_dir.joinpath(f"make-output.log") - # Execute make with target and cores/2 + # Source setup script and execute make with target and cores/2 if target: - command = ["make", target, "--jobs=$(($(nproc)/2))"] + command = [f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && make {target} --jobs=$(($(nproc)/2))"] else: - command = ["make", "--jobs=$(($(nproc)/2))"] + command = [f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && make --jobs=$(($(nproc)/2))"] self.logger.info(f"Command used in directory {makefile_location}: {' '.join(command)}") @@ -305,7 +302,7 @@ class TestRunner: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True, executable="/bin/bash") # Execute the command using a subprocess and not save the output #result = subprocess.run(command, text=True) @@ -334,12 +331,16 @@ class TestRunner: output_file = self.log_dir.joinpath(f"{test_name}-output.log") os.chdir(self.sim_dir) + # Source setup script and delete output from log on whatever test command gets run + command = f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && " + if test_extensions: - command = [test_type, test_name] + test_extensions + commandext = [test_type, test_name] + test_extensions self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name} {' '.join(test_extensions)}") else: - command = [test_type, test_name] + commandext = [test_type, test_name] self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name}") + command += " ".join(commandext) # Execute the command using subprocess and save the output into a file @@ -348,15 +349,15 @@ class TestRunner: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True, executable="/bin/bash") except Exception as e: - self.logger.error("There was an error in running the tests in the run_tests function: {e}") + self.logger.error(f"There was an error in running the tests in the run_tests function: {e}") # Check if the command executed successfuly if result.returncode or result.returncode == 0: - self.logger.info(f"Test ran successfuly. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}") + self.logger.info(f"Test ran successfuly. Test name: {test_name}, test extension: {' '.join(test_extensions)}") return True, output_file else: - self.logger.error(f"Error making test. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}") + self.logger.error(f"Error making test. Test name: {test_name}, test extension: {' '.join(test_extensions)}") return False, output_file From f258384596fd2975f14d3e6f0f86ebc4fb44ba52 Mon Sep 17 00:00:00 2001 From: Huda-10xe Date: Fri, 1 Nov 2024 06:07:49 -0700 Subject: [PATCH 19/42] Adding sv32 coverpoins --- config/rv32gc/coverage.svh | 2 ++ sim/questa/wally.do | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config/rv32gc/coverage.svh b/config/rv32gc/coverage.svh index 2eb52541f..97496a8b9 100644 --- a/config/rv32gc/coverage.svh +++ b/config/rv32gc/coverage.svh @@ -25,3 +25,5 @@ // Privileged extensions `include "ZicsrM_coverage.svh" +`include "RV32VM_coverage.svh" +`include "RV32VM_PMP_coverage.svh" diff --git a/sim/questa/wally.do b/sim/questa/wally.do index a53a0e3c7..c692b06e1 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -181,7 +181,7 @@ if {$DEBUG > 0} { # suppress spurious warnngs about # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/priv +incdir+${FCRVVI}/common +incdir+${FCRVVI}" +set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/priv +incdir+${FCRVVI}/rv32_priv +incdir+${FCRVVI}/common +incdir+${FCRVVI}" set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv" vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286 From eddae8e1a676045cf10144af5238ef62c8c43799 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 1 Nov 2024 13:02:17 -0500 Subject: [PATCH 20/42] Fixed ShiftEdge and SampleEdge to not always include PhaseOneOffset. Before, it worked in simulation, but not on the FPGA. --- src/uncore/spi_controller.sv | 37 ++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 605685b4b..576884374 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -243,10 +243,34 @@ module spi_controller ( SampleEdge <= 0; EndOfFrameDelay <= 0; end else begin - ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; - PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; - SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; - EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; + case(SckMode) + 2'b00: begin + ShiftEdge <= SPICLK & SCLKenable & ~LastBit & Transmitting; + SampleEdge <= ~SPICLK & SCLKenable & Transmitting & ~DelayIsNext; + EndOfFrameDelay <= SPICLK & SCLKenable & LastBit & Transmitting; + end + 2'b01: begin + ShiftEdge <= ~SPICLK & SCLKenable & ~LastBit & Transmitting & PhaseOneOffset; + SampleEdge <= SPICLK & SCLKenable & Transmitting & ~DelayIsNext; + EndOfFrameDelay <= ~SPICLK & SCLKenable & LastBit & Transmitting; + PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + end + 2'b10: begin + ShiftEdge <= ~SPICLK & SCLKenable & ~LastBit & Transmitting; + SampleEdge <= SPICLK & SCLKenable & Transmitting & ~DelayIsNext; + EndOfFrameDelay <= ~SPICLK & SCLKenable & LastBit & Transmitting; + end + 2'b11: begin + ShiftEdge <= SPICLK & SCLKenable & ~LastBit & Transmitting & PhaseOneOffset; + SampleEdge <= ~SPICLK & SCLKenable & Transmitting & ~DelayIsNext; + EndOfFrameDelay <= SPICLK & SCLKenable & LastBit & Transmitting; + PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + end + // ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; + // PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; + // SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; + // EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; + endcase end end @@ -314,8 +338,9 @@ module spi_controller ( SCKCS: begin // SCKCS case -------------------------------------- if (EndOfSCKCS) begin if (~ContinueTransmitD) begin - if (CSMode == AUTOMODE) NextState = INACTIVE; - else if (CSMode == HOLDMODE) NextState = HOLD; + // if (CSMode == AUTOMODE) NextState = INACTIVE; + if (CSMode == HOLDMODE) NextState = HOLD; + else NextState = INACTIVE; end else begin if (HasINTERCS) NextState = INTERCS; else NextState = TRANSMIT; From 960d72295c9dd34d2acda6de30e92edb8f7e01f0 Mon Sep 17 00:00:00 2001 From: naichewa Date: Fri, 1 Nov 2024 11:27:41 -0700 Subject: [PATCH 21/42] Removed SPI hardware interlock test cases --- addins/cvw-arch-verif | 2 +- addins/riscv-arch-test | 2 +- .../references/WALLY-spi-01.reference_output | 40 -------- .../rv32i_m/privilege/src/WALLY-spi-01.S | 95 ------------------- .../references/WALLY-spi-01.reference_output | 40 -------- .../rv64i_m/privilege/src/WALLY-spi-01.S | 88 ----------------- 6 files changed, 2 insertions(+), 265 deletions(-) diff --git a/addins/cvw-arch-verif b/addins/cvw-arch-verif index bbcba7864..189974e49 160000 --- a/addins/cvw-arch-verif +++ b/addins/cvw-arch-verif @@ -1 +1 @@ -Subproject commit bbcba78647080dee82e96bc1b8ff9cd9a3cf7fa1 +Subproject commit 189974e497d7b8d2c08bb1d151b1ccdeaf3a64c9 diff --git a/addins/riscv-arch-test b/addins/riscv-arch-test index ce04b4930..7152865ac 160000 --- a/addins/riscv-arch-test +++ b/addins/riscv-arch-test @@ -1 +1 @@ -Subproject commit ce04b4930545ae4c81e2f3b6f6935e2aac08679e +Subproject commit 7152865aca51062c87ff2cbb014e199a24bdc874 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output index 425866ac2..027e02f54 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output @@ -238,46 +238,6 @@ 0000001F -00000062 # hardware interlock - -00000026 - -000000D2 - -0000002D - -00000048 - -00000037 - -00000026 - -00000015 - -00000084 - -00000073 - -00000062 - -00000051 - -00000046 - -00000035 - -00000024 - -00000013 - -00000064 - -00000053 - -00000042 - -00000031 - 00000001 #watermark interrupts 00000000 #read mip diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S index 4048c4c4c..a004a5ea0 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S @@ -547,101 +547,6 @@ test_cases: #.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end #.4byte rx_data, 0x000000F0, read32_test # read rx_data -#=========== Test Hardware Interlock ================ - -# interlock in base case - -.4byte fmt, 0x00080000, write32_test # reset fmt register -.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.4byte tx_data, 0x00000062, write32_test # initiate transmission -.4byte sck_mode, 0x00000002, write32_test # flip polarity during transmission -.4byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated -.4byte 0x0, 0x00000001, spi_data_wait -.4byte rx_data, 0x00000062, read32_test -.4byte rx_data, 0x00000026, read32_test # clear rx fifo -.4byte sck_mode, 0x00000000, write32_test # reset polarity - -# interlock in case where cs_mode is auto, but there is minimal intercs delay - -.4byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay -.4byte tx_data, 0x000000D2, write32_test # initiate transmission -.4byte sck_mode, 0x00000002, write32_test # flip sck polarity -.4byte tx_data, 0x0000002D, write32_test # transmit second frame -.4byte 0x0, 0x00000001, spi_data_wait -.4byte rx_data, 0x000000D2, read32_test -.4byte rx_data, 0x0000002D, read32_test # clear rx fifo -.4byte sck_mode, 0x00000000, write32_test # reset polarity - -# interlock in case where cs_mode = hold, 0 intercs delay -.4byte delay0, 0x00010001, write32_test # reset delay0 -.4byte sck_mode, 0x00000000, write32_test # reset polarity -.4byte cs_mode, 0x00000002, write32_test # set cs_mode to hold -.4byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo -.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.4byte sck_mode, 0x00000000, write32_test # flip polarity again -.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.4byte rx_data, 0x00000048, read32_test -.4byte rx_data, 0x00000037, read32_test -.4byte rx_data, 0x00000026, read32_test -.4byte rx_data, 0x00000015, read32_test #clear rx fifo - -# interlock in case where cs_mode = hold, intercs delay - -.4byte sck_mode, 0x00000000, write32_test # reset polarity -.4byte delay1, 0x00010001, write32_test # set intercs delay to 1 -.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.4byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo -.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.4byte sck_mode, 0x00000000, write32_test # flip polarity again -.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.4byte rx_data, 0x00000084, read32_test -.4byte rx_data, 0x00000073, read32_test -.4byte rx_data, 0x00000062, read32_test -.4byte rx_data, 0x00000051, read32_test #clear rx fifo - -# repeat previous set of tests with cs_mode = off - -.4byte cs_mode, 0x00000003, write32_test # set cs_mode to hold -.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.4byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo -.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.4byte sck_mode, 0x00000000, write32_test # flip polarity again -.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.4byte rx_data, 0x00000046, read32_test -.4byte rx_data, 0x00000035, read32_test -.4byte rx_data, 0x00000024, read32_test -.4byte rx_data, 0x00000013, read32_test #clear rx fifo - -# interlock in case where cs_mode = hold, intercs delay - -.4byte sck_mode, 0x00000000, write32_test # reset polarity -.4byte delay1, 0x00000000, write32_test # set intercs delay to 0 -.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.4byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo -.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.4byte sck_mode, 0x00000000, write32_test # flip polarity again -.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.4byte rx_data, 0x00000064, read32_test -.4byte rx_data, 0x00000053, read32_test -.4byte rx_data, 0x00000042, read32_test -.4byte rx_data, 0x00000031, read32_test #clear rx fifo - - - - - - - - - # =========== Test watermark interrupts =========== diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output index 7520479ce..8d9ae8bbc 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output @@ -238,46 +238,6 @@ 00000000 0000001F 00000000 -00000062 # hardware interlock -00000000 -00000026 -00000000 -000000D2 -00000000 -0000002D -00000000 -00000048 -00000000 -00000037 -00000000 -00000026 -00000000 -00000015 -00000000 -00000084 -00000000 -00000073 -00000000 -00000062 -00000000 -00000051 -00000000 -00000046 -00000000 -00000035 -00000000 -00000024 -00000000 -00000013 -00000000 -00000064 -00000000 -00000053 -00000000 -00000042 -00000000 -00000031 -00000000 00000001 #watermark interrupts 00000000 00000000 #read mip diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S index 2a04f02f0..0f189b5e6 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S @@ -551,94 +551,6 @@ test_cases: #.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end #.8byte rx_data, 0x000000F0, read32_test # read rx_data -#=========== Test Hardware Interlock ================ - -# interlock in base case - -.8byte fmt, 0x00080000, write32_test # reset fmt register -.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.8byte tx_data, 0x00000062, write32_test # initiate transmission -.8byte sck_mode, 0x00000002, write32_test # flip polarity during transmission -.8byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated -.8byte 0x0, 0x00000001, spi_data_wait -.8byte rx_data, 0x00000062, read32_test -.8byte rx_data, 0x00000026, read32_test # clear rx fifo -.8byte sck_mode, 0x00000000, write32_test # reset polarity - -# interlock in case where cs_mode is auto, but there is minimal intercs delay - -.8byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay -.8byte tx_data, 0x000000D2, write32_test # initiate transmission -.8byte sck_mode, 0x00000002, write32_test # flip sck polarity -.8byte tx_data, 0x0000002D, write32_test # transmit second frame -.8byte 0x0, 0x00000001, spi_data_wait -.8byte rx_data, 0x000000D2, read32_test -.8byte rx_data, 0x0000002D, read32_test # clear rx fifo -.8byte sck_mode, 0x00000000, write32_test # reset polarity - -# interlock in case where cs_mode = hold, 0 intercs delay -.8byte delay0, 0x00010001, write32_test # reset delay0 -.8byte sck_mode, 0x00000000, write32_test # reset polarity -.8byte cs_mode, 0x00000002, write32_test # set cs_mode to hold -.8byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo -.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.8byte sck_mode, 0x00000000, write32_test # flip polarity again -.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.8byte rx_data, 0x00000048, read32_test -.8byte rx_data, 0x00000037, read32_test -.8byte rx_data, 0x00000026, read32_test -.8byte rx_data, 0x00000015, read32_test #clear rx fifo - -# interlock in case where cs_mode = hold, intercs delay - -.8byte sck_mode, 0x00000000, write32_test # reset polarity -.8byte delay1, 0x00010001, write32_test # set intercs delay to 1 -.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.8byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo -.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.8byte sck_mode, 0x00000000, write32_test # flip polarity again -.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.8byte rx_data, 0x00000084, read32_test -.8byte rx_data, 0x00000073, read32_test -.8byte rx_data, 0x00000062, read32_test -.8byte rx_data, 0x00000051, read32_test #clear rx fifo - -# repeat previous set of tests with cs_mode = off - -.8byte cs_mode, 0x00000003, write32_test # set cs_mode to hold -.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.8byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo -.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.8byte sck_mode, 0x00000000, write32_test # flip polarity again -.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.8byte rx_data, 0x00000046, read32_test -.8byte rx_data, 0x00000035, read32_test -.8byte rx_data, 0x00000024, read32_test -.8byte rx_data, 0x00000013, read32_test #clear rx fifo - -# interlock in case where cs_mode = hold, intercs delay - -.8byte sck_mode, 0x00000000, write32_test # reset polarity -.8byte delay1, 0x00000000, write32_test # set intercs delay to 0 -.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock -.8byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo -.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame) -.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end -.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock -.8byte sck_mode, 0x00000000, write32_test # flip polarity again -.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame -.8byte rx_data, 0x00000064, read32_test -.8byte rx_data, 0x00000053, read32_test -.8byte rx_data, 0x00000042, read32_test -.8byte rx_data, 0x00000031, read32_test #clear rx fifo - - From 3fda7ecb81a2179aeb385daa6fbe9db30ccf492a Mon Sep 17 00:00:00 2001 From: naichewa Date: Fri, 1 Nov 2024 13:09:41 -0700 Subject: [PATCH 22/42] Fix SPI regression tests --- .../riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S | 2 +- .../riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S index a004a5ea0..94defaf87 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S @@ -553,7 +553,7 @@ test_cases: # Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables SETUP_PLIC - +.4byte fmt, 0x00080000, write32_test # reset format register .4byte delay1, 0x0000001, write32_test # reset delay1 register .4byte cs_mode, 0x00000000, write32_test # reset cs_mode .4byte tx_mark, 0x00000001, write32_test # set transmit watermark to 1 (any entry turns mark off) diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S index 0f189b5e6..23cfd169a 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S @@ -564,7 +564,7 @@ test_cases: # Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables SETUP_PLIC - +.8byte fmt, 0x00080000, write32_test # reset format register .8byte delay1, 0x0000001, write32_test # reset delay1 register .8byte cs_mode, 0x00000000, write32_test # reset cs_mode .8byte sck_div, 0x00000100, write32_test # lower SPI clock rate so reads are done at correct time when ICACHE not supported From e881bd31203a04a0c6e84b57dafd1461533a0b4f Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 1 Nov 2024 17:04:07 -0500 Subject: [PATCH 23/42] Changed the condition for TransmitStart fsm to avoid edge condition. --- src/uncore/spi_apb.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 5d3352154..a15068f10 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -273,7 +273,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; - WAIT: if (TransmitFIFOReadEmpty & ~Transmitting & ~TransmitRegLoaded) NextState = READY; + WAIT: if (/*TransmitFIFOReadEmpty &*/ ~Transmitting & ~TransmitRegLoaded) NextState = READY; else NextState = WAIT; default: NextState = READY; endcase From c197d4a3c661b702f7be99ce0188836040fc134b Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 1 Nov 2024 17:35:55 -0500 Subject: [PATCH 24/42] Cleaned up some code. Still more work to do there. --- src/uncore/spi_apb.sv | 2 +- src/uncore/spi_controller.sv | 40 +++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index a15068f10..e6bd34b6a 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -273,7 +273,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; - WAIT: if (/*TransmitFIFOReadEmpty &*/ ~Transmitting & ~TransmitRegLoaded) NextState = READY; + WAIT: if (~Transmitting & ~TransmitRegLoaded) NextState = READY; else NextState = WAIT; default: NextState = READY; endcase diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 576884374..9e7bd6aeb 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -80,6 +80,9 @@ module spi_controller ( logic PreSampleEdge; // logic ShiftEdge; // logic SampleEdge; + logic ShiftEdgePulse; + logic SampleEdgePulse; + logic EndOfFramePulse; // Frame stuff logic [3:0] BitNum; @@ -220,6 +223,7 @@ module spi_controller ( // EndOfFrame <= 1'b0; // end + // TODO: Rename EndOfFrameDelay to EndOfFrame and remove this logic if (~TransmitStart) begin EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; end @@ -236,35 +240,39 @@ module spi_controller ( // Delay ShiftEdge and SampleEdge by a half PCLK period // Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges. // Sweeeeeeeeeet... + + assign ShiftEdgePulse = SCLKenable & ~LastBit & Transmitting; + assign SampleEdgePulse = SCLKenable & Transmitting & ~DelayIsNext; + assign EndOfFramePulse = SCLKenable & LastBit & Transmitting; + always_ff @(posedge ~PCLK) begin if (~PRESETn | TransmitStart) begin ShiftEdge <= 0; PhaseOneOffset <= 0; SampleEdge <= 0; EndOfFrameDelay <= 0; - end else begin - case(SckMode) + end else begin + PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + case(SckMode) 2'b00: begin - ShiftEdge <= SPICLK & SCLKenable & ~LastBit & Transmitting; - SampleEdge <= ~SPICLK & SCLKenable & Transmitting & ~DelayIsNext; - EndOfFrameDelay <= SPICLK & SCLKenable & LastBit & Transmitting; + ShiftEdge <= SPICLK & ShiftEdgePulse; + SampleEdge <= ~SPICLK & SampleEdgePulse; + EndOfFrameDelay <= SPICLK & EndOfFramePulse; end 2'b01: begin - ShiftEdge <= ~SPICLK & SCLKenable & ~LastBit & Transmitting & PhaseOneOffset; - SampleEdge <= SPICLK & SCLKenable & Transmitting & ~DelayIsNext; - EndOfFrameDelay <= ~SPICLK & SCLKenable & LastBit & Transmitting; - PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + ShiftEdge <= ~SPICLK & ShiftEdgePulse & PhaseOneOffset; + SampleEdge <= SPICLK & SampleEdgePulse; + EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; end 2'b10: begin - ShiftEdge <= ~SPICLK & SCLKenable & ~LastBit & Transmitting; - SampleEdge <= SPICLK & SCLKenable & Transmitting & ~DelayIsNext; - EndOfFrameDelay <= ~SPICLK & SCLKenable & LastBit & Transmitting; + ShiftEdge <= ~SPICLK & ShiftEdgePulse; + SampleEdge <= SPICLK & SampleEdgePulse; + EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; end 2'b11: begin - ShiftEdge <= SPICLK & SCLKenable & ~LastBit & Transmitting & PhaseOneOffset; - SampleEdge <= ~SPICLK & SCLKenable & Transmitting & ~DelayIsNext; - EndOfFrameDelay <= SPICLK & SCLKenable & LastBit & Transmitting; - PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + ShiftEdge <= SPICLK & ShiftEdgePulse & PhaseOneOffset; + SampleEdge <= ~SPICLK & SampleEdgePulse; + EndOfFrameDelay <= SPICLK & EndOfFramePulse; end // ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; // PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; From 2a8e213f209d7bd280f9622c1fa53c4489e9cec1 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sat, 2 Nov 2024 12:33:27 -0500 Subject: [PATCH 25/42] Wrote a script that can take hexadecimal bytes from a file and write them to an output file and an sd card. --- linux/sdcard/write-bytes.sh | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100755 linux/sdcard/write-bytes.sh diff --git a/linux/sdcard/write-bytes.sh b/linux/sdcard/write-bytes.sh new file mode 100755 index 000000000..ba847e876 --- /dev/null +++ b/linux/sdcard/write-bytes.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# This file writes a bunch of bytes to the flash card based on a text +# file input with bytes written in hexadecimal. + +INPUTFILE="" +OUTPUTFILE="" + +ARGS=() +while [ $OPTIND -le "$#" ] ; do + if getopts "hi:o:" arg ; then + case "${arg}" in + h) help + ;; + i) INPUTFILE=${OPTARG} + ;; + o) OUTPUTFILE=${OPTARG} + ;; + esac + else + ARGS+=("${!OPTIND}") + ((OPTIND++)) + fi +done + +SDCARD=${ARGS[0]} + +if [ ! -e $INPUTFILE ] ; then + echo -e "Error: Input file $INPUTFILE does not exist." + exit 1 +fi + +if [ -e $OUTPUTFILE ] ; then + echo -e "Error: Output file $OUTPUTFILE already exists." + exit 1 +fi + +for word in $(cat "$INPUTFILE") +do + echo -en "\x$word" >> $OUTPUTFILE +done + +dd if=$OUTPUTFILE of="$SDCARD" From e33c2f7a8ca03e48d93177dd561dc6563f0be414 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sat, 2 Nov 2024 12:36:45 -0500 Subject: [PATCH 26/42] Added usage and help functions to write-bytes.sh --- linux/sdcard/write-bytes.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linux/sdcard/write-bytes.sh b/linux/sdcard/write-bytes.sh index ba847e876..83a8481e5 100755 --- a/linux/sdcard/write-bytes.sh +++ b/linux/sdcard/write-bytes.sh @@ -3,6 +3,15 @@ # This file writes a bunch of bytes to the flash card based on a text # file input with bytes written in hexadecimal. +usage() { echo "Usage: $0 [-zh] [-b ] " 1>&2; exit 1; } + +help() { + echo "Usage: $0 [OPTIONS] " + echo " -i Input text file with hex bytes." + echo " -b Output binary file." + exit 0; +} + INPUTFILE="" OUTPUTFILE="" From 9c3937165743200a9bc560ca455fa0adf2dfb0cb Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sat, 2 Nov 2024 14:14:31 -0500 Subject: [PATCH 27/42] Reverted bootloader optimizations to second iteration. Working on last optimization. --- fpga/zsbl/boot.c | 74 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index d9a824a49..7665b2df2 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -135,45 +135,45 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { /* crc = crc16(crc, x); */ /* } while (--n > 0); */ - /* n = 512/8; */ - /* do { */ - /* // Send 8 dummy bytes (fifo should be empty) */ - /* for (j = 0; j < 8; j++) { */ - /* spi_sendbyte(0xff); */ - /* } */ - - /* // Reset counter. Process bytes AS THEY COME IN. */ - /* for (j = 0; j < 8; j++) { */ - /* while (!(read_reg(SPI_IP) & 2)) {} */ - /* uint8_t x = spi_readbyte(); */ - /* *p++ = x; */ - /* // crc = crc16(crc, x); */ - /* crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff; */ - /* } */ - /* } while(--n > 0); */ - - n = 512; - // Initially fill the transmit fifo - for (j = 0; j < 8; j++) { - spi_sendbyte(0xff); - } - - - while (n > 0) { - // Wait for bytes to be received - while (!(read_reg(SPI_IP) & 2)) {} - // Read byte - uint8_t x = spi_readbyte(); - // Send another dummy byte - if (n > 8) { + n = 512/8; + do { + // Send 8 dummy bytes (fifo should be empty) + for (j = 0; j < 8; j++) { spi_sendbyte(0xff); } - // Place received byte into memory - *p++ = x; - // Update CRC16 with fast table based method - crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff; - n = n - 1; - } + + // Reset counter. Process bytes AS THEY COME IN. + for (j = 0; j < 8; j++) { + while (!(read_reg(SPI_IP) & 2)) {} + uint8_t x = spi_readbyte(); + *p++ = x; + // crc = crc16(crc, x); + crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff; + } + } while(--n > 0); + + /* n = 512; */ + /* // Initially fill the transmit fifo */ + /* for (j = 0; j < 8; j++) { */ + /* spi_sendbyte(0xff); */ + /* } */ + + + /* while (n > 0) { */ + /* // Wait for bytes to be received */ + /* while (!(read_reg(SPI_IP) & 2)) {} */ + /* // Read byte */ + /* uint8_t x = spi_readbyte(); */ + /* // Send another dummy byte */ + /* if (n > 8) { */ + /* spi_sendbyte(0xff); */ + /* } */ + /* // Place received byte into memory */ + /* *p++ = x; */ + /* // Update CRC16 with fast table based method */ + /* crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff; */ + /* n = n - 1; */ + /* } */ // Read CRC16 and check crc_exp = ((uint16_t)spi_dummy() << 8); From 674d008f23a40445be7f6ffee9405337772c3a78 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sat, 2 Nov 2024 14:31:05 -0500 Subject: [PATCH 28/42] Added headers to files. --- linux/sdcard/flash-sd.sh | 26 ++++++++++++++++++++++++++ linux/sdcard/write-bytes.sh | 28 ++++++++++++++++++++++++++++ src/uncore/spi_apb.sv | 6 ++++-- src/uncore/spi_controller.sv | 5 ++--- 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/linux/sdcard/flash-sd.sh b/linux/sdcard/flash-sd.sh index 7a2c58d42..31e6ee45f 100755 --- a/linux/sdcard/flash-sd.sh +++ b/linux/sdcard/flash-sd.sh @@ -1,4 +1,30 @@ #!/bin/bash +########################################### +## flash-sd.sh +## +## Written: Jacob Pease jacobpease@protonmail.com +## Created: August 22, 2023 +## +## Purpose: A script to flash an sd card with a bootable linux image. +## +## A component of the CORE-V-WALLY configurable RISC-V project. +## https://github.com/openhwgroup/cvw +## +## Copyright (C) 2021-24 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. +################################################################################################ # Exit on any error (return code != 0) # set -e diff --git a/linux/sdcard/write-bytes.sh b/linux/sdcard/write-bytes.sh index 83a8481e5..b9c312ceb 100755 --- a/linux/sdcard/write-bytes.sh +++ b/linux/sdcard/write-bytes.sh @@ -1,4 +1,32 @@ #!/bin/bash +########################################### +## write-bytes.sh +## +## Written: Jacob Pease jacobpease@protonmail.com +## Created: November 2nd, 2024 +## Modified: +## +## Purpose: Write a sequence of bytes from text file to an output file and a flash card. +## +## A component of the CORE-V-WALLY configurable RISC-V project. +## https://github.com/openhwgroup/cvw +## +## Copyright (C) 2021-24 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. +################################################################################################ + # This file writes a bunch of bytes to the flash card based on a text # file input with bytes written in hexadecimal. diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index e6bd34b6a..293c2c2b5 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -1,7 +1,9 @@ /////////////////////////////////////////// // spi_apb.sv // -// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu 11/16/2022 +// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu +// Jacob Pease jacobpease@protonmail.com (October 29th, 2024) +// Created: November 16th, 2022 // // Purpose: SPI peripheral // @@ -13,7 +15,7 @@ // // A component of the Wally configurable RISC-V project. // -// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University // // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 9e7bd6aeb..19b32cab3 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -1,9 +1,8 @@ /////////////////////////////////////////// // spi_controller.sv // -// Written: jacobpease@protonmail.com +// Written: Jacob Pease jacobpease@protonmail.com // Created: October 28th, 2024 -// Modified: // // Purpose: Controller logic for SPI // @@ -12,7 +11,7 @@ // 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 +// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University // // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // From c64c6c4cf1e7e183636f05da4640bdee25dba2e8 Mon Sep 17 00:00:00 2001 From: Jordan Carlin Date: Sat, 2 Nov 2024 16:09:14 -0700 Subject: [PATCH 29/42] Fix reverted submodules --- .gitmodules | 3 ++- addins/cvw-arch-verif | 2 +- addins/riscv-arch-test | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index eed0bb58f..34a374174 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,9 +25,10 @@ sparseCheckout = true path = addins/verilog-ethernet url = https://github.com/rosethompson/verilog-ethernet.git -[submodule "cvw-arch-verif"] +[submodule "addins/cvw-arch-verif"] path = addins/cvw-arch-verif url = https://github.com/openhwgroup/cvw-arch-verif + ignore = dirty [submodule "addins/riscvISACOV"] path = addins/riscvISACOV url = https://github.com/riscv-verification/riscvISACOV.git diff --git a/addins/cvw-arch-verif b/addins/cvw-arch-verif index 189974e49..6d658b7b4 160000 --- a/addins/cvw-arch-verif +++ b/addins/cvw-arch-verif @@ -1 +1 @@ -Subproject commit 189974e497d7b8d2c08bb1d151b1ccdeaf3a64c9 +Subproject commit 6d658b7b42c83fd584008d72964cc75d0876b769 diff --git a/addins/riscv-arch-test b/addins/riscv-arch-test index 7152865ac..3843c736e 160000 --- a/addins/riscv-arch-test +++ b/addins/riscv-arch-test @@ -1 +1 @@ -Subproject commit 7152865aca51062c87ff2cbb014e199a24bdc874 +Subproject commit 3843c736e427a2b52a0d06e6220b073afa4be401 From a9e6962cd4de508d8d0e60366f4981784f24b89e Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sun, 3 Nov 2024 00:35:40 -0500 Subject: [PATCH 30/42] Removed unused signals and renamed other signals. Removed a bunch of delay counters and simply reuse one counter for all delay types. Tested on FPGA and it also passes regression. --- src/uncore/spi_apb.sv | 90 ++++++++++--------- src/uncore/spi_controller.sv | 163 ++++++++++++----------------------- 2 files changed, 101 insertions(+), 152 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 293c2c2b5..38fa07f42 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -85,11 +85,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // SPI Controller signals logic SCLKenable; logic EndOfFrame; - logic EndOfFrameDelay; logic Transmitting; logic InactiveState; logic [3:0] FrameLength; + // logic ResetSCLKenable; logic TransmitStart; logic TransmitStartD; @@ -100,14 +100,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // FIFO FSM signals // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] - logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; - logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; - logic TransmitFIFOWriteIncrement; - logic [7:0] TransmitFIFOReadData; + logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + logic TransmitFIFOFull, TransmitFIFOEmpty; + logic TransmitFIFOWriteInc; + logic TransmitFIFOReadInc; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + logic [7:0] TransmitReadData; + // logic ReceiveFIFOWriteInc; - logic ReceiveFIFOReadIncrement; - logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; + logic ReceiveFIFOReadInc; + logic ReceiveFIFOFull, ReceiveFIFOEmpty; /* verilator lint_off UNDRIVEN */ logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs @@ -115,16 +117,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission) // Shift reg signals - logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg - logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg - logic [7:0] TransmitReg; // Transmit shift register + logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg + logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg + logic [7:0] TransmitReg; // Transmit shift register logic [7:0] ReceiveShiftReg; // Receive shift register logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB - logic TransmitLoad; // Determines when to load TransmitReg - logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + logic TransmitLoad; // Determines when to load TransmitReg + logic TransmitRegLoaded; // Shift stuff due to Format register? - logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) + logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) logic [3:0] LeftShiftAmount; // Determines left shift amount to left-align data when little endian logic [7:0] ASR; // AlignedReceiveShiftReg @@ -180,14 +182,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if (Memwrite) case(Entry) - SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0]; + SPI_TXDATA: if (~TransmitFIFOFull) TransmitData[7:0] <= Din[7:0]; endcase /* verilator lint_off CASEINCOMPLETE */ // According to FU540 spec: Once interrupt is pending, it will remain set until number // of entries in tx/rx fifo is strictly more/less than tx/rxmark InterruptPending[0] <= TransmitReadMark; - InterruptPending[1] <= RecieveWriteMark; + InterruptPending[1] <= ReceiveWriteMark; case(Entry) // Flop to sample inputs SPI_SCKDIV: Dout <= {20'b0, SckDiv}; @@ -198,8 +200,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( SPI_DELAY0: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]}; SPI_DELAY1: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]}; SPI_FMT: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0}; - SPI_TXDATA: Dout <= {TransmitFIFOWriteFull, 23'b0, 8'b0}; - SPI_RXDATA: Dout <= {ReceiveFIFOReadEmpty, 23'b0, ReceiveData[7:0]}; + SPI_TXDATA: Dout <= {TransmitFIFOFull, 23'b0, 8'b0}; + SPI_RXDATA: Dout <= {ReceiveFIFOEmpty, 23'b0, ReceiveData[7:0]}; SPI_TXMARK: Dout <= {29'b0, TransmitWatermark}; SPI_RXMARK: Dout <= {29'b0, ReceiveWatermark}; SPI_IE: Dout <= {30'b0, InterruptEnable}; @@ -208,11 +210,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase end - // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) - // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv - // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase - // When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). - // SPI Controller module ------------------------------------------- // This module controls state and timing signals that drive the rest of this module assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV); @@ -224,38 +221,40 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Register Inputs SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff - TransmitFIFOReadEmpty, + TransmitFIFOEmpty, // Timing - SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, EndOfFrameDelay, + SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, // State stuff Transmitting, InactiveState, // Outputs SPICLK); // Transmit FIFO --------------------------------------------------- + + // txFIFO write increment logic always_ff @(posedge PCLK) if (~PRESETn) begin - TransmitFIFOWriteIncrement <= 1'b0; + TransmitFIFOWriteInc <= 1'b0; end else begin - TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); + TransmitFIFOWriteInc <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull); end + // txFIFO read increment logic always_ff @(posedge PCLK) if (~PRESETn) begin - TransmitFIFOReadIncrement <= 1'b0; + TransmitFIFOReadInc <= 1'b0; end else if (SCLKenable) begin - TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; + TransmitFIFOReadInc <= TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty) ; end // Check whether TransmitReg has been loaded. // We use this signal to prevent returning to the Ready state for TransmitStart - logic TransmitRegLoaded; always_ff @(posedge PCLK) begin if (~PRESETn) begin TransmitRegLoaded <= 1'b0; end else if (TransmitLoad) begin TransmitRegLoaded <= 1'b1; - end else if (ShiftEdge | EndOfFrameDelay) begin + end else if (ShiftEdge | EndOfFrame) begin TransmitRegLoaded <= 1'b0; end end @@ -272,7 +271,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // State machine for starting transmissions always_comb begin case (CurrState) - READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; + READY: if (~TransmitFIFOEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; WAIT: if (~Transmitting & ~TransmitRegLoaded) NextState = READY; @@ -288,42 +287,41 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( else if (SCLKenable) TransmitStartD <= 1'b0; spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, - TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, + TransmitFIFOWriteInc, TransmitFIFOReadInc, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], - TransmitFIFOReadData[7:0], - TransmitFIFOWriteFull, - TransmitFIFOReadEmpty, + TransmitReadData[7:0], + TransmitFIFOFull, + TransmitFIFOEmpty, TransmitWriteMark, TransmitReadMark); - // Receive FIFO ---------------------------------------------------- always_ff @(posedge PCLK) if (~PRESETn) begin - ReceiveFIFOReadIncrement <= 1'b0; + ReceiveFIFOReadInc <= 1'b0; end else begin - ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); + ReceiveFIFOReadInc <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc); end always_ff @(posedge PCLK) if (~PRESETn) begin ReceiveFIFOWriteInc <= 1'b0; end else if (SCLKenable) begin - ReceiveFIFOWriteInc <= EndOfFrameDelay; + ReceiveFIFOWriteInc <= EndOfFrame; end - + spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, - ReceiveFIFOWriteInc, ReceiveFIFOReadIncrement, + ReceiveFIFOWriteInc, ReceiveFIFOReadInc, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], - ReceiveFIFOWriteFull, - ReceiveFIFOReadEmpty, - RecieveWriteMark, RecieveReadMark); + ReceiveFIFOFull, + ReceiveFIFOEmpty, + ReceiveWriteMark, ReceiveReadMark); // Transmit shift register - assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~TransmitFIFOReadEmpty); - assign TransmitDataEndian = Format[0] ? {<<{TransmitFIFOReadData[7:0]}} : TransmitFIFOReadData[7:0]; + assign TransmitLoad = TransmitStart | (EndOfFrame & ~TransmitFIFOEmpty); + assign TransmitDataEndian = Format[0] ? {<<{TransmitReadData[7:0]}} : TransmitReadData[7:0]; always_ff @(posedge PCLK) if(~PRESETn) TransmitReg <= 8'b0; else if (TransmitLoad) TransmitReg <= TransmitDataEndian; diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 19b32cab3..0400d2956 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -51,8 +51,7 @@ module spi_controller ( output logic SCLKenable, output logic ShiftEdge, output logic SampleEdge, - output logic EndOfFrame, - output logic EndOfFrameDelay, + output logic EndOfFrame, output logic Transmitting, output logic InactiveState, output logic SPICLK @@ -63,43 +62,31 @@ module spi_controller ( localparam AUTOMODE = 2'b00; localparam OFFMODE = 2'b11; + // FSM States typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; statetype CurrState, NextState; // SCLKenable stuff logic [11:0] DivCounter; - // logic SCLKenable; - // logic SCLKenableEarly; - logic ZeroDiv; - logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK! - + logic SCK; // Shift and Sample Edges - logic PreShiftEdge; - logic PreSampleEdge; - // logic ShiftEdge; - // logic SampleEdge; + logic EdgePulse; logic ShiftEdgePulse; logic SampleEdgePulse; logic EndOfFramePulse; + logic PhaseOneOffset; // Frame stuff logic [3:0] BitNum; logic LastBit; - //logic EndOfFrame; - //logic EndOfFrameDelay; - logic PhaseOneOffset; // Transmit Stuff logic ContinueTransmit; - - // SPIOUT Stuff - // logic TransmitLoad; - logic [7:0] TransmitReg; - //logic Transmitting; logic EndTransmission; - - logic HoldMode; + logic ContinueTransmitD; // TODO: Could be replaced by TransmitRegLoaded? + logic NextEndDelay; + logic CurrentEndDelay; // Delay Stuff logic [7:0] cssck; @@ -116,13 +103,12 @@ module spi_controller ( logic EndOfSCKCS; logic EndOfINTERCS; logic EndOfINTERXFR; + logic EndOfDelay; - logic [7:0] CSSCKCounter; - logic [7:0] SCKCSCounter; - logic [7:0] INTERCSCounter; - logic [7:0] INTERXFRCounter; + logic [7:0] DelayCounter; logic DelayIsNext; + logic DelayState; // Convenient Delay Reg Names assign cssck = Delay0[7:0]; @@ -137,23 +123,25 @@ module spi_controller ( assign HasINTERXFR = interxfr > 8'b0; // Have we hit full delay for any of the delays? - assign EndOfCSSCK = CSSCKCounter == cssck; - assign EndOfSCKCS = SCKCSCounter == sckcs; - assign EndOfINTERCS = INTERCSCounter == intercs; - assign EndOfINTERXFR = INTERXFRCounter == interxfr; + assign EndOfCSSCK = (DelayCounter == cssck) & (CurrState == CSSCK); + assign EndOfSCKCS = (DelayCounter == sckcs) & (CurrState == SCKCS); + assign EndOfINTERCS = (DelayCounter == intercs) & (CurrState == INTERCS); + assign EndOfINTERXFR = (DelayCounter == interxfr) & (CurrState == INTERXFR); + + assign EndOfDelay = EndOfCSSCK | EndOfSCKCS | EndOfINTERCS | EndOfINTERXFR; // Clock Signal Stuff ----------------------------------------------- // I'm going to handle all clock stuff here, including ShiftEdge and // SampleEdge. This makes sure that SPICLK is an output of a register // and it properly synchronizes signals. - - assign SCLKenable = DivCounter == SckDiv; - // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; - assign LastBit = (BitNum == FrameLength - 4'b1); - //assign EndOfFrame = SCLKenable & LastBit & Transmitting; - assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay; - assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay; + // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) + // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv + // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase + assign SCLKenable = DivCounter == SckDiv; + + assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame; + assign EndTransmission = txFIFOReadEmpty & EndOfFrame; always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -161,13 +149,7 @@ module spi_controller ( SPICLK <= SckMode[1]; SCK <= 0; BitNum <= 4'h0; - PreShiftEdge <= 0; - PreSampleEdge <= 0; - EndOfFrame <= 0; - CSSCKCounter <= 0; - SCKCSCounter <= 0; - INTERCSCounter <= 0; - INTERXFRCounter <= 0; + DelayCounter <= 0; end else begin // TODO: Consolidate into one delay counter since none of the // delays happen at the same time? @@ -176,29 +158,12 @@ module spi_controller ( end else if (SCLKenable) begin SCK <= ~SCK; end - - if ((CurrState == CSSCK) & SCK & SCLKenable) begin - CSSCKCounter <= CSSCKCounter + 8'd1; - end else if (SCLKenable & EndOfCSSCK) begin - CSSCKCounter <= 8'd0; - end - - if ((CurrState == SCKCS) & SCK & SCLKenable) begin - SCKCSCounter <= SCKCSCounter + 8'd1; - end else if (SCLKenable & EndOfSCKCS) begin - SCKCSCounter <= 8'd0; - end - - if ((CurrState == INTERCS) & SCK & SCLKenable) begin - INTERCSCounter <= INTERCSCounter + 8'd1; - end else if (SCLKenable & EndOfINTERCS) begin - INTERCSCounter <= 8'd0; - end - - if ((CurrState == INTERXFR) & SCK & SCLKenable) begin - INTERXFRCounter <= INTERXFRCounter + 8'd1; - end else if (SCLKenable & EndOfINTERXFR) begin - INTERXFRCounter <= 8'd0; + + // Counter for all four delay types + if (DelayState & SCK & SCLKenable) begin + DelayCounter <= DelayCounter + 8'd1; + end else if (SCLKenable & EndOfDelay) begin + DelayCounter <= 8'd0; end // SPICLK Logic @@ -215,85 +180,70 @@ module spi_controller ( DivCounter <= DivCounter + 12'd1; end - // EndOfFrame controller - // if (SckDiv > 0 ? SCLKenableEarly & LastBit & SPICLK : LastBit & ~SPICLK) begin - // EndOfFrame <= 1'b1; - // end else begin - // EndOfFrame <= 1'b0; - // end - - // TODO: Rename EndOfFrameDelay to EndOfFrame and remove this logic - if (~TransmitStart) begin - EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; - end - // Increment BitNum if (ShiftEdge & Transmitting) begin BitNum <= BitNum + 4'd1; - end else if (EndOfFrameDelay) begin + end else if (EndOfFrame) begin BitNum <= 4'b0; end end end + // The very last bit in a frame of any length. + assign LastBit = (BitNum == FrameLength - 4'b1); + + // Any SCLKenable pulse aligns with leading or trailing edge during + // Transmission. We can use this signal as the basis for ShiftEdge + // and SampleEdge. + assign EdgePulse = SCLKenable & Transmitting; + + // Possible pulses for all edge types. Combined with SPICLK to get + // edges for different phase and polarity modes. + assign ShiftEdgePulse = EdgePulse & ~LastBit; + assign SampleEdgePulse = EdgePulse & ~DelayIsNext; + assign EndOfFramePulse = EdgePulse & LastBit; + // Delay ShiftEdge and SampleEdge by a half PCLK period // Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges. // Sweeeeeeeeeet... - - assign ShiftEdgePulse = SCLKenable & ~LastBit & Transmitting; - assign SampleEdgePulse = SCLKenable & Transmitting & ~DelayIsNext; - assign EndOfFramePulse = SCLKenable & LastBit & Transmitting; - always_ff @(posedge ~PCLK) begin if (~PRESETn | TransmitStart) begin ShiftEdge <= 0; PhaseOneOffset <= 0; SampleEdge <= 0; - EndOfFrameDelay <= 0; + EndOfFrame <= 0; end else begin - PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrame; case(SckMode) 2'b00: begin ShiftEdge <= SPICLK & ShiftEdgePulse; SampleEdge <= ~SPICLK & SampleEdgePulse; - EndOfFrameDelay <= SPICLK & EndOfFramePulse; + EndOfFrame <= SPICLK & EndOfFramePulse; end 2'b01: begin ShiftEdge <= ~SPICLK & ShiftEdgePulse & PhaseOneOffset; SampleEdge <= SPICLK & SampleEdgePulse; - EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; + EndOfFrame <= ~SPICLK & EndOfFramePulse; end 2'b10: begin ShiftEdge <= ~SPICLK & ShiftEdgePulse; SampleEdge <= SPICLK & SampleEdgePulse; - EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; + EndOfFrame <= ~SPICLK & EndOfFramePulse; end 2'b11: begin ShiftEdge <= SPICLK & ShiftEdgePulse & PhaseOneOffset; SampleEdge <= ~SPICLK & SampleEdgePulse; - EndOfFrameDelay <= SPICLK & EndOfFramePulse; + EndOfFrame <= SPICLK & EndOfFramePulse; end - // ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; - // PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; - // SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; - // EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; endcase end end - // typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; - // statetype CurrState, NextState; - - assign HoldMode = CSMode == HOLDMODE; - // assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); - - logic ContinueTransmitD; - logic NextEndDelay; - logic CurrentEndDelay; - + // Logic for continuing to transmit through Delay states after end of frame assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR; assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR; - + + // always_ff @(posedge PCLK) begin if (~PRESETn) begin ContinueTransmitD <= 1'b0; @@ -326,7 +276,7 @@ module spi_controller ( case(CSMode) AUTOMODE: begin if (EndTransmission) NextState = INACTIVE; - else if (EndOfFrameDelay) NextState = SCKCS; + else if (EndOfFrame) NextState = SCKCS; else NextState = TRANSMIT; end HOLDMODE: begin @@ -386,6 +336,7 @@ module spi_controller ( assign Transmitting = CurrState == TRANSMIT; assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR); + assign DelayState = (CurrState == CSSCK | CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR); assign InactiveState = CurrState == INACTIVE | CurrState == INTERCS; endmodule From 746eb67004f77e4a526d08f7d5b543d97bd80d3a Mon Sep 17 00:00:00 2001 From: slmnemo Date: Thu, 31 Oct 2024 15:39:38 -0700 Subject: [PATCH 31/42] Initial pass of removing pre-done source.sh dependency in nightly build --- bin/nightly_build.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/bin/nightly_build.py b/bin/nightly_build.py index cb8583eef..b675fceca 100755 --- a/bin/nightly_build.py +++ b/bin/nightly_build.py @@ -261,9 +261,6 @@ class TestRunner: cvw = folder.joinpath("cvw") self.logger.info(f"cvw is: {cvw}") - # set the WALLY environmental variable to the new repository - os.environ["WALLY"] = str(cvw) - self.cvw = cvw self.sim_dir = cvw.joinpath("bin") self.base_parent_dir = folder @@ -292,11 +289,11 @@ class TestRunner: output_file = self.log_dir.joinpath(f"make-{target}-output.log") else: output_file = self.log_dir.joinpath(f"make-output.log") - # Execute make with target and cores/2 + # Source setup script and execute make with target and cores/2 if target: - command = ["make", target, "--jobs=$(($(nproc)/2))"] + command = [f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && make {target} --jobs=$(($(nproc)/2))"] else: - command = ["make", "--jobs=$(($(nproc)/2))"] + command = [f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && make --jobs=$(($(nproc)/2))"] self.logger.info(f"Command used in directory {makefile_location}: {' '.join(command)}") @@ -305,7 +302,7 @@ class TestRunner: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True, executable="/bin/bash") # Execute the command using a subprocess and not save the output #result = subprocess.run(command, text=True) @@ -334,12 +331,16 @@ class TestRunner: output_file = self.log_dir.joinpath(f"{test_name}-output.log") os.chdir(self.sim_dir) + # Source setup script and delete output from log on whatever test command gets run + command = f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && " + if test_extensions: - command = [test_type, test_name] + test_extensions + commandext = [test_type, test_name] + test_extensions self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name} {' '.join(test_extensions)}") else: - command = [test_type, test_name] + commandext = [test_type, test_name] self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name}") + command += " ".join(commandext) # Execute the command using subprocess and save the output into a file @@ -348,15 +349,15 @@ class TestRunner: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True, executable="/bin/bash") except Exception as e: - self.logger.error("There was an error in running the tests in the run_tests function: {e}") + self.logger.error(f"There was an error in running the tests in the run_tests function: {e}") # Check if the command executed successfuly if result.returncode or result.returncode == 0: - self.logger.info(f"Test ran successfuly. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}") + self.logger.info(f"Test ran successfuly. Test name: {test_name}, test extension: {' '.join(test_extensions)}") return True, output_file else: - self.logger.error(f"Error making test. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}") + self.logger.error(f"Error making test. Test name: {test_name}, test extension: {' '.join(test_extensions)}") return False, output_file From 4cf049f83eba74a0e09d1ea240d3714910241f97 Mon Sep 17 00:00:00 2001 From: slmnemo Date: Sun, 3 Nov 2024 12:54:24 -0800 Subject: [PATCH 32/42] Fixed dryrun not doing anything in regression-wally --- bin/regression-wally | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/regression-wally b/bin/regression-wally index 0a7a8fa69..cc0588bf6 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -539,7 +539,7 @@ def main(): num_fail = 0 results = {} for config in configs: - results[config] = pool.apply_async(run_test_case,(config,)) + results[config] = pool.apply_async(run_test_case,(config, args.dryrun)) for (config,result) in results.items(): try: num_fail+=result.get(timeout=TIMEOUT_DUR) From 226170a76fefaae5a0fc58e80347bc98df12ddf8 Mon Sep 17 00:00:00 2001 From: slmnemo Date: Sun, 3 Nov 2024 14:00:17 -0800 Subject: [PATCH 33/42] Added symlink so Imperas.dv can load buildroot in lockstep and a corresponding waiver for buildroot in lockstep in wsim --- bin/wsim | 2 +- config/buildroot/imperas.ic | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 config/buildroot/imperas.ic diff --git a/bin/wsim b/bin/wsim index ca44e22a6..8f71c4297 100755 --- a/bin/wsim +++ b/bin/wsim @@ -65,7 +65,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che print("ELF file not found: " + args.testsuite) exit(1) -if(args.lockstep and not args.testsuite.endswith('.elf')): +if(args.lockstep and not args.testsuite.endswith('.elf') and not args.testsuite == "buildroot"): print(f"Invalid Options. Cannot run a testsuite, {args.testsuite} with lockstep. Must run a single elf.") exit(1) diff --git a/config/buildroot/imperas.ic b/config/buildroot/imperas.ic new file mode 120000 index 000000000..43af05a2d --- /dev/null +++ b/config/buildroot/imperas.ic @@ -0,0 +1 @@ +../rv64gc/imperas.ic \ No newline at end of file From 0c6e9dc770ba7787895e977da55005276a89a09f Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Sun, 3 Nov 2024 14:21:55 -0800 Subject: [PATCH 34/42] Fixed rmm rounding mode bug --- src/fpu/fround.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fpu/fround.sv b/src/fpu/fround.sv index 6c37d2973..b5c1b975e 100644 --- a/src/fpu/fround.sv +++ b/src/fpu/fround.sv @@ -126,7 +126,7 @@ module fround import cvw::*; #(parameter cvw_t P) ( 3'b001: RoundUp = 0; // RZ 3'b010: RoundUp = Xs & (Rp | Tp); // RN 3'b011: RoundUp = ~Xs & (Rp | Tp); // RP - 3'b101: RoundUp = Rp; // RNTA + 3'b100: RoundUp = Rp; // RNTA default: RoundUp = 0; // should never happen endcase From d55a16b678da56b6e145e767fd912b25b511b063 Mon Sep 17 00:00:00 2001 From: slmnemo Date: Sun, 3 Nov 2024 19:50:59 -0800 Subject: [PATCH 35/42] Added derivative configs to imperas.ic searches --- bin/wsim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/wsim b/bin/wsim index 8f71c4297..dde022bed 100755 --- a/bin/wsim +++ b/bin/wsim @@ -91,6 +91,8 @@ prefix = "" if (args.lockstep or args.lockstepverbose or args.fcov or args.fcovimp): if (args.sim == "questa" or args.sim == "vcs"): prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic" + if not os.path.isfile(prefix): # If config is a derivative, look for imperas.ic in derivative configs + prefix = "IMPERAS_TOOLS=" + os.path.join(WALLY, "config", "deriv", args.config, "imperas.ic") # Force Questa to use 64-bit mode, sometimes it defaults to 32-bit even on 64-bit machines if (args.sim == "questa"): prefix = "MTI_VCO_MODE=64 " + prefix From 37c459ba892e22eb4d8d021538b8fa9f4edc2224 Mon Sep 17 00:00:00 2001 From: slmnemo Date: Sun, 3 Nov 2024 19:51:30 -0800 Subject: [PATCH 36/42] Added hardlinks to derivative configs to imperas.ic for lockstep --- bin/derivgen.pl | 10 ++++++++++ config/buildroot/imperas.ic | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) delete mode 120000 config/buildroot/imperas.ic diff --git a/bin/derivgen.pl b/bin/derivgen.pl index 58991faae..5dee10243 100755 --- a/bin/derivgen.pl +++ b/bin/derivgen.pl @@ -88,6 +88,16 @@ foreach my $key (@derivnames) { open(my $unmod, $configunmod) or die "Could not open file '$configunmod' $!"; open(my $fh, '>>', $config) or die "Could not open file '$config' $!"; + # Create symlink to imperas.ic for deriv if exists + my $baseimperas_ic = "$ENV{WALLY}/config/$basederiv{$key}/imperas.ic"; + if (! -e $baseimperas_ic) { + my $baseimperas_ic = "$ENV{WALLY}/config/deriv/$basederiv{$key}/config.vh"; + } + if (-e $baseimperas_ic) { # If imperas.ic exists for base derivative, create hardlink to it + my $imperas_ic = "$dir/imperas.ic"; + system("ln -T $baseimperas_ic $imperas_ic"); + } + my $datestring = localtime(); my %hit = (); print $fh "// Config $key automatically derived from $basederiv{$key} on $datestring using derivgen.pl\n"; diff --git a/config/buildroot/imperas.ic b/config/buildroot/imperas.ic deleted file mode 120000 index 43af05a2d..000000000 --- a/config/buildroot/imperas.ic +++ /dev/null @@ -1 +0,0 @@ -../rv64gc/imperas.ic \ No newline at end of file From 611a77775c0d407707ad527993139b596d002abc Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Mon, 4 Nov 2024 09:48:04 -0600 Subject: [PATCH 37/42] Removed unused files form linux/testvector-generation. Only genInitMem.sh and fixBinMem.c remain. The latter could be replaced with objcopy. --- linux/testvector-generation/EmulateLinux.sh | 47 ---- .../testvector-generation/checkpointSweep.sh | 6 - linux/testvector-generation/debug.sh | 21 -- .../disassembleBootTrace.py | 74 ------ .../filterTrapsToInterrupts.py | 68 ----- linux/testvector-generation/genCheckpoint.sh | 146 ----------- linux/testvector-generation/genRecording.sh | 38 --- linux/testvector-generation/genTrace.sh | 54 ---- .../testvector-generation/parseGDBtoTrace.py | 243 ------------------ linux/testvector-generation/parsePlicState.py | 106 -------- linux/testvector-generation/parseQEMUtoGDB.py | 145 ----------- linux/testvector-generation/parseState.py | 99 ------- linux/testvector-generation/parseUartState.py | 50 ---- 13 files changed, 1097 deletions(-) delete mode 100755 linux/testvector-generation/EmulateLinux.sh delete mode 100755 linux/testvector-generation/checkpointSweep.sh delete mode 100755 linux/testvector-generation/debug.sh delete mode 100755 linux/testvector-generation/disassembleBootTrace.py delete mode 100755 linux/testvector-generation/filterTrapsToInterrupts.py delete mode 100755 linux/testvector-generation/genCheckpoint.sh delete mode 100755 linux/testvector-generation/genRecording.sh delete mode 100755 linux/testvector-generation/genTrace.sh delete mode 100755 linux/testvector-generation/parseGDBtoTrace.py delete mode 100755 linux/testvector-generation/parsePlicState.py delete mode 100755 linux/testvector-generation/parseQEMUtoGDB.py delete mode 100755 linux/testvector-generation/parseState.py delete mode 100755 linux/testvector-generation/parseUartState.py diff --git a/linux/testvector-generation/EmulateLinux.sh b/linux/testvector-generation/EmulateLinux.sh deleted file mode 100755 index e2b50af4d..000000000 --- a/linux/testvector-generation/EmulateLinux.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -usage() { echo "Usage: $0 [-h] [-b ] [-d ]" 1>&2; exit 1; } - -help() { - echo "Usage: $0 [OPTIONS] " - echo " -b get images from given buildroot" - echo " -d specify device tree to use" - exit 0; -} - -# defaults -imageDir=$RISCV/buildroot/output/images -DEVICE_TREE=${imageDir}/wally-virt.dtb - -# Process options and arguments. The following code grabs the single -# sdcard device argument no matter where it is in the positional -# parameters list. -ARGS=() -while [ $OPTIND -le "$#" ] ; do - if getopts "hb:d:" arg ; then - case "${arg}" in - h) help - ;; - b) BUILDROOT=${OPTARG} - ;; - d) DEVICE_TREE=${OPTARG} - ;; - esac - else - ARGS+=("${!OPTIND}") - ((OPTIND++)) - fi -done - -# File location variables -imageDir=$BUILDROOT/output/images - -tvDir=$RISCV/linux-testvectors -tcpPort=1239 - -# QEMU Simulation -qemu-system-riscv64 \ --M virt -m 256M -dtb $DEVICE_TREE \ --nographic \ --bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" --singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on diff --git a/linux/testvector-generation/checkpointSweep.sh b/linux/testvector-generation/checkpointSweep.sh deleted file mode 100755 index 075ca253c..000000000 --- a/linux/testvector-generation/checkpointSweep.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -for index in {450..500}; -do - instrs=$(($index*1000000)) - echo "y" | nice -n 5 ./genCheckpoint.sh $instrs -done diff --git a/linux/testvector-generation/debug.sh b/linux/testvector-generation/debug.sh deleted file mode 100755 index 7ca3e9b15..000000000 --- a/linux/testvector-generation/debug.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -tcpPort=1239 - -# QEMU Simulation -qemu-system-riscv64 \ --M virt -dtb $imageDir/wally-virt.dtb \ --nographic \ --bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ --singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on -# > ./qemu-serial \ -# -gdb tcp::$tcpPort -S) \ -# & riscv64-unknown-elf-gdb -quiet \ -# -ex "set pagination off" \ -# -ex "set logging overwrite on" \ -# -ex "set logging redirect on" \ -# -ex "set confirm off" \ -# -ex "target extended-remote :$tcpPort" \ -# -ex "maintenance packet Qqemu.PhyMemMode:1" \ -# -ex "file $imageDir/vmlinux" diff --git a/linux/testvector-generation/disassembleBootTrace.py b/linux/testvector-generation/disassembleBootTrace.py deleted file mode 100755 index ac36fd36e..000000000 --- a/linux/testvector-generation/disassembleBootTrace.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python3 -# -# disassembleBootTrace.py -# David_Harris@hmc.edu 22 November 2023 -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Reads boottrace.log and disassembles the machine code -# - -import csv -import os -import re - -# read a file from sim/logs/boottrace.log and extract the second comma-separated field containing the instruction -print("Reading boottrace.log") -trace = [] -count = 0 -with open('../../sim/logs/boottrace.log') as f: - reader = csv.reader(f, delimiter=',') - for row in reader: - trace.append(row) - count = count + 1 - if count > 50000000: - break -f.close() - -print("Disassembling boottrace.log instructions") -# Write an assembly language file with the machine code -with (open('boottrace.S', 'w')) as f: - f.write('main:\n') - for row in trace: - instr = row[1] - # scrape off leading white space from instr - instr = instr.lstrip() - # check if last character indicates an compressed or uncompressed instruction - lastNibble = instr[-1] - if (lastNibble == '3' or lastNibble == '7' or lastNibble == 'b' or lastNibble == 'f'): - # uncompressed - f.write('.word 0x' + instr + '\n') - else: - # compressed - instr = instr[-4:] - f.write('.hword 0x' + instr + '\n') -f.close() - -# Then assemble and disassemble the file -os.system('riscv64-unknown-elf-gcc -march=rv64gqc_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom -mabi=lp64d -c boottrace.S') -os.system('riscv64-unknown-elf-objdump -D boottrace.o > boottrace.objdump') - -# Patch disassembly back into boottrace -print("Inserting disassembly into trace") -dumpedLines = [] -with (open('boottrace.objdump', 'r')) as f: - lines = f.readlines() - f.close() -lines = lines[7:] # skip header -p = r'[^:]*:\s*(\S*)\s*(.*)' -for line in lines: - match = re.search(p, line) - if (match): - dump = [match.group(1), match.group(2)] - dumpedLines.append(dump) - -linenum = 0 -for i in range(len(trace)): - row = trace[i] - row.insert(2, dumpedLines[i][1]) - -# write trace back to csv file -print("Writing trace back to boottrace_disasm.log") -with (open('boottrace_disasm.log', 'w')) as f: - writer = csv.writer(f) - writer.writerows(trace) -f.close() diff --git a/linux/testvector-generation/filterTrapsToInterrupts.py b/linux/testvector-generation/filterTrapsToInterrupts.py deleted file mode 100755 index 7476e110f..000000000 --- a/linux/testvector-generation/filterTrapsToInterrupts.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 -import sys, os -from functools import reduce - -################ -# Helper Funcs # -################ - -def tokenize(string): - tokens = [] - token = '' - whitespace = 0 - prevWhitespace = 0 - for char in string: - prevWhitespace = whitespace - whitespace = char in ' \t\n' - if (whitespace): - if ((not prevWhitespace) and (token != '')): - tokens.append(token) - token = '' - else: - token = token + char - return tokens - -def strip0x(num): - return num[2:] - -def stripZeroes(num): - num = num.strip('0') - if num=='': - return '0' - else: - return num - -############# -# Main Code # -############# -print("Begin filtering traps down to just external interrupts.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error filterTrapsToInterrupts.py expects 1 arg: ') -tvDir = sys.argv[1]+'/' -trapsFilePath = tvDir+'traps.txt' -if not os.path.exists(trapsFilePath): - sys.exit('Error input file '+trapsFilePath+'not found') - -with open(tvDir+'interrupts.txt', 'w') as interruptsFile: - with open(trapsFilePath, 'r') as trapsFile: - while True: - trap = trapsFile.readline() - if trap == '': - break - trapType = trap.split(' ')[-1] - if ('interrupt' in trap) and (('external' in trapType) or ('m_timer' in trapType)): # no s_timer because that is not controlled by CLINT - interruptsFile.write(trap) # overall line - interruptsFile.write(trapsFile.readline()) # attempted instr count - interruptsFile.write(trapsFile.readline()) # hart # - interruptsFile.write(trapsFile.readline()) # asynchronous - interruptsFile.write(trapsFile.readline()) # cause - interruptsFile.write(trapsFile.readline()) # epc - interruptsFile.write(trapsFile.readline()) # tval - interruptsFile.write(trapsFile.readline()) # description - else: - for i in range(7): - trapsFile.readline() - -print("Finished filtering traps down to just external interrupts.") diff --git a/linux/testvector-generation/genCheckpoint.sh b/linux/testvector-generation/genCheckpoint.sh deleted file mode 100755 index f12223f54..000000000 --- a/linux/testvector-generation/genCheckpoint.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/bash -tcpPort=1238 -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -recordFile="$tvDir/all.qemu" -traceFile="$tvDir/all.txt" - -# Parse Commandline Arg -if [ "$#" -ne 1 ]; then - echo "genCheckpoint requires 1 argument: " >&2 - exit 1 -fi -instrs=$1 -if ! [ "$instrs" -eq "$instrs" ] 2> /dev/null -then - echo "Error expected integer number of instructions, got $instrs" >&2 - exit 1 -fi - -checkPtDir="$tvDir/checkpoint$instrs" -outTraceFile="$checkPtDir/all.txt" -rawStateFile="$checkPtDir/stateGDB.txt" -rawUartStateFile="$checkPtDir/uartStateGDB.txt" -uartStateFile="$checkPtDir/checkpoint-UART" -rawPlicStateFile="$checkPtDir/plicStateGDB.txt" -plicStateFile="$checkPtDir/checkpoint-PLIC" -rawRamFile="$checkPtDir/ramGDB.bin" -ramFile="$checkPtDir/ram.bin" - -read -p "This scripts is going to create a checkpoint at $instrs instrs. -Is that what you wanted? (y/n) " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]] -then - echo "Creating checkpoint at $instrs instructions!" - if [ ! -d "$tvDir" ]; then - echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it. For example:">&2 - echo " sudo mkdir -p $tvDir">&2 - exit 1 - fi - test -w $tvDir - if [ ! $? -eq 0 ]; then - echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it. For example:">&2 - echo " sudo chmod -R a+rw $tvDir">&2 - exit 1 - fi - - mkdir -p $checkPtDir - - # Identify instruction in trace - instr=$(sed "${instrs}q;d" "$traceFile") - echo "Found ${instrs}th instr: ${instr}" - pc=$(echo $instr | cut -d " " -f1) - asm=$(echo $instr | cut -d " " -f2) - occurences=$(($(head -$instrs "$traceFile" | grep -c "${pc} ${asm}")-1)) - echo "It occurs ${occurences} times before the ${instrs}th instr." - - # Create GDB script because GDB is terrible at handling arguments / variables - cat > genCheckpoint.gdb <<- end_of_script - set pagination off - set logging overwrite on - set logging redirect on - set confirm off - target extended-remote :$tcpPort - maintenance packet Qqemu.PhyMemMode:1 - file $imageDir/vmlinux - # Step over reset vector into actual code - stepi 100 - shell echo \"GDB proceeding to checkpoint at $instrs instrs, pc $pc\" - b *0x$pc - ignore 1 $occurences - c - shell echo \"Reached checkpoint at $instrs instrs\" - shell echo \"GDB storing CPU state to $rawStateFile\" - set logging file $rawStateFile - set logging on - info all-registers - set logging off - shell echo \"GDB storing UART state to $rawUartStateFile\" - # Save value of LCR - set \$LCR=*0x10000003 & 0xff - set logging file $rawUartStateFile - set logging on - # Change LCR to set DLAB=0 to be able to read RBR and IER - set {char}0x10000003 &= ~0x80 - x/1xb 0x10000000 - x/1xb 0x10000001 - x/1xb 0x10000002 - # But log original value of LCR - printf "0x10000003:\t0x%02x\n", \$LCR - x/1xb 0x10000004 - x/1xb 0x10000005 - x/1xb 0x10000006 - x/1xb 0x10000007 - set logging off - shell echo \"GDB storing PLIC state to $rawPlicStateFile\" - shell echo \"Note: this dumping assumes a maximum of 63 PLIC sources\" - set logging file $rawPlicStateFile - set logging on - # Priority Levels for sources 1 thru 63 - x/63xw 0x0C000004 - # Interrupt Enables for sources 1 thru 63 for contexts 0 and 1 - x/2xw 0x0C002000 - x/2xw 0x0C002080 - # Global Priority Threshold for contexts 0 and 1 - x/1xw 0x0C200000 - x/1xw 0x0C201000 - set logging off - shell echo \"GDB storing RAM to $rawRamFile\" - dump binary memory $rawRamFile 0x80000000 0x87ffffff - kill - q -end_of_script - - # GDB+QEMU - echo "Starting QEMU in replay mode with attached GDB script at $(date +%H:%M:%S)" - (qemu-system-riscv64 \ - -M virt -dtb $imageDir/wally-virt.dtb \ - -nographic \ - -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ - -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \ - -gdb tcp::$tcpPort -S \ - 1>./qemu-serial) \ - & riscv64-unknown-elf-gdb --quiet -x genCheckpoint.gdb - - echo "Completed GDB script at $(date +%H:%M:%S)" - - # Post-Process GDB outputs - ./parseState.py "$checkPtDir" - ./parseUartState.py "$checkPtDir" - ./parsePlicState.py "$checkPtDir" - echo "Changing Endianness at $(date +%H:%M:%S)" - make fixBinMem - ./fixBinMem "$rawRamFile" "$ramFile" - echo "Copying over a truncated trace" - tail -n+$instrs $traceFile > $outTraceFile - - echo "Checkpoint completed at $(date +%H:%M:%S)" - echo "You may want to restrict write access to $tvDir now and give cad ownership of it." - echo "Run the following:" - echo " sudo chown -R cad:cad $tvDir" - echo " sudo chmod -R go-w $tvDir" -fi - diff --git a/linux/testvector-generation/genRecording.sh b/linux/testvector-generation/genRecording.sh deleted file mode 100755 index 2696253c5..000000000 --- a/linux/testvector-generation/genRecording.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -recordFile="$tvDir/all.qemu" -DEVICE_TREE=${imageDir}/wally-virt.dtb - -read -p "Warning: running this script will overwrite $recordFile -Would you like to proceed? (y/n) " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]] -then - if [ ! -d "$tvDir" ]; then - echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it. For example:">&2 - echo " sudo mkdir -p $tvDir">&2 - exit 1 - fi - test -w $tvDir - if [ ! $? -eq 0 ]; then - echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it. For example:">&2 - echo " sudo chmod -R a+rw $tvDir">&2 - exit 1 - fi - - echo "Launching QEMU in record mode!" - qemu-system-riscv64 \ - -M virt -m 256M -dtb $DEVICE_TREE \ - -nographic \ - -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ - -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=record,rrfile=$recordFile - - echo "genRecording.sh completed!" - echo "You may want to restrict write access to $tvDir now and give cad ownership of it." - echo "Run the following:" - echo " sudo chown -R cad:cad $tvDir" - echo " sudo chmod -R go-w $tvDir" -fi diff --git a/linux/testvector-generation/genTrace.sh b/linux/testvector-generation/genTrace.sh deleted file mode 100755 index 5d04592ce..000000000 --- a/linux/testvector-generation/genTrace.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -tcpPort=1234 -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -recordFile="$tvDir/all.qemu" -traceFile="$tvDir/all.txt" -trapsFile="$tvDir/traps.txt" -interruptsFile="$tvDir/interrupts.txt" -DEVICE_TREE=${imageDir}/wally-virt.dtb - -read -p "Warning: running this script will overwrite the contents of: - * $traceFile - * $trapsFile - * $interruptsFile -Would you like to proceed? (y/n) " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]] -then - if [ ! -d "$tvDir" ]; then - echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it. For example:">&2 - echo " sudo mkdir -p $tvDir">&2 - exit 1 - fi - test -w $tvDir - if [ ! $? -eq 0 ]; then - echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it. For example:">&2 - echo " sudo chmod -R a+rw $tvDir">&2 - exit 1 - fi - - touch $traceFile - touch $trapsFile - touch $interruptsFile - - # QEMU Simulation - echo "Launching QEMU in replay mode!" - (qemu-system-riscv64 \ - -M virt -m 256M -dtb $DEVICE_TREE \ - -nographic \ - -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ - -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \ - -d nochain,cpu,in_asm,int \ - 2>&1 >./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $trapsFile > $traceFile) - - ./filterTrapsToInterrupts.py $tvDir - - echo "genTrace.sh completed!" - echo "You may want to restrict write access to $tvDir now and give cad ownership of it." - echo "Run the following:" - echo " sudo chown -R cad:cad $tvDir" - echo " sudo chmod -R go-w $tvDir" -fi diff --git a/linux/testvector-generation/parseGDBtoTrace.py b/linux/testvector-generation/parseGDBtoTrace.py deleted file mode 100755 index 96ad464ed..000000000 --- a/linux/testvector-generation/parseGDBtoTrace.py +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env python3 -import sys, fileinput, re - -# Rose Thompson -# July 27, 2021 -# Rewrite of the linux trace parser. - - -InstrStartDelim = '=>' -InstrEndDelim = '-----' - -#InputFile = 'noparse.txt' -#InputFile = sys.stdin -#InputFile = 'temp.txt' -#OutputFile = 'parsedAll.txt' - -HUMAN_READABLE = False - -def toDict(lst): - 'Converts the list of register values to a dictionary' - dct= {} - for item in lst: - regTup = item.split() - dct[regTup[0]] = int(regTup[2], 10) - del dct['pc'] - return dct - -def whichClass(text, Regs): - 'Which instruction class?' - #print(text, Regs) - if text[0:2] == 'ld' or text[0:2] == 'lw' or text[0:2] == 'lh' or text[0:2] == 'lb': - return ('load', WhatAddr(text, Regs), None, WhatMemDestSource(text)) - elif text[0:2] == 'sd' or text[0:2] == 'sw' or text[0:2] == 'sh' or text[0:2] == 'sb': - return ('store', WhatAddr(text, Regs), WhatMemDestSource(text), None) - elif text[0:3] == 'amo': - return ('amo', WhatAddrAMO(text, Regs), WhatMemDestSource(text), WhatMemDestSource(text)) - elif text[0:2] == 'lr': - return ('lr', WhatAddrLR(text, Regs), None, WhatMemDestSource(text)) - elif text[0:2] == 'sc': - return ('sc', WhatAddrSC(text, Regs), WhatMemDestSource(text), None) - else: - return ('other', None, None, None) - -def whatChanged(dct0, dct1): - 'Compares two dictionaries of instrution registers and indicates which registers changed' - dct = {} - for key in dct0: - if (dct1[key] != dct0[key]): - dct[key] = dct1[key] - return dct - -def WhatMemDestSource(text): - ''''What is the destination register. Used to compute where the read data is - on a load or the write data on a store.''' - return text.split()[1].split(',')[0] - -def WhatAddr(text, Regs): - 'What is the data memory address?' - Imm = text.split(',')[1] - (Imm, Src) = Imm.split('(') - Imm = int(Imm.strip(), 10) - Src = Src.strip(')').strip() - RegVal = Regs[Src] - return Imm + RegVal - -def WhatAddrAMO(text, Regs): - 'What is the data memory address?' - Src = text.split('(')[1] - Src = Src.strip(')').strip() - return Regs[Src] - -def WhatAddrLR(text, Regs): - 'What is the data memory address?' - Src = text.split('(')[1] - Src = Src.strip(')').strip() - return Regs[Src] - -def WhatAddrSC(text, Regs): - 'What is the data memory address?' - Src = text.split('(')[1] - Src = Src.strip(')').strip() - return Regs[Src] - -def PrintInstr(instr): - if instr[2] == None: - return - ChangedRegisters = instr[4] - GPR = '' - CSR = [] - for key in ChangedRegisters: - # filter out csr which are not checked. - if(key in RegNumber): - if(RegNumber[key] < 32): - # GPR - if(HUMAN_READABLE): - GPR = '{:-2d} {:016x}'.format(RegNumber[key], ChangedRegisters[key]) - else: - GPR = '{:d} {:x}'.format(RegNumber[key], ChangedRegisters[key]) - else: - if(HUMAN_READABLE): - CSR.extend([key, '{:016x}'.format(ChangedRegisters[key])]) - else: - CSR.extend([key, '{:x}'.format(ChangedRegisters[key])]) - - CSRStr = ' '.join(CSR) - - #print(instr) - - if (HUMAN_READABLE == True): - outString='{:016x} {:08x} {:25s}'.format(instr[0], instr[1], instr[2]) - if(len(GPR) != 0): - outString+=' GPR {}'.format(GPR) - if(instr[3] == 'load' or instr[3] == 'lr'): - outString+=' MemR {:016x} {:016x} {:016x}'.format(instr[5], 0, instr[7]) - if(instr[3] == 'store'): - outString+='\t\t\t MemW {:016x} {:016x} {:016x}'.format(instr[5], instr[6], 0) - if(len(CSR) != 0): - outString+=' CSR {}'.format(CSRStr) - else: - outString='{:x} {:x} {:s}'.format(instr[0], instr[1], instr[2].replace(' ', '_')) - if(len(GPR) != 0): - outString+=' GPR {}'.format(GPR) - if(instr[3] == 'load' or instr[3] == 'lr'): - outString+=' MemR {:x} {:x} {:x}'.format(instr[5], 0, instr[7]) - if(instr[3] == 'store'): - outString+=' MemW {:x} {:x} {:x}'.format(instr[5], instr[6], 0) - if(len(CSR) != 0): - outString+=' CSR {}'.format(CSRStr) - outString+='\n' - return outString - -# ========= -# Main Code -# ========= -# Parse argument for interrupt file -if len(sys.argv) != 2: - sys.exit('Error parseGDBtoTrace.py expects 1 arg:\n >') -interruptFname = sys.argv[1] -# reg number -RegNumber = {'zero': 0, 'ra': 1, 'sp': 2, 'gp': 3, 'tp': 4, 't0': 5, 't1': 6, 't2': 7, 's0': 8, 's1': 9, 'a0': 10, 'a1': 11, 'a2': 12, 'a3': 13, 'a4': 14, 'a5': 15, 'a6': 16, 'a7': 17, 's2': 18, 's3': 19, 's4': 20, 's5': 21, 's6': 22, 's7': 23, 's8': 24, 's9': 25, 's10': 26, 's11': 27, 't3': 28, 't4': 29, 't5': 30, 't6': 31, 'mhartid': 32, 'mstatus': 33, 'mip': 34, 'mie': 35, 'mideleg': 36, 'medeleg': 37, 'mtvec': 38, 'stvec': 39, 'mepc': 40, 'sepc': 41, 'mcause': 42, 'scause': 43, 'mtval': 44, 'stval': 45, 'mscratch': 46, 'sscratch': 47, 'satp': 48} -# initial state -CurrentInstr = ['0', '0', None, 'other', {'zero': 0, 'ra': 0, 'sp': 0, 'gp': 0, 'tp': 0, 't0': 0, 't1': 0, 't2': 0, 's0': 0, 's1': 0, 'a0': 0, 'a1': 0, 'a2': 0, 'a3': 0, 'a4': 0, 'a5': 0, 'a6': 0, 'a7': 0, 's2': 0, 's3': 0, 's4': 0, 's5': 0, 's6': 0, 's7': 0, 's8': 0, 's9': 0, 's10': 0, 's11': 0, 't3': 0, 't4': 0, 't5': 0, 't6': 0, 'mhartid': 0, 'mstatus': 0, 'mip': 0, 'mie': 0, 'mideleg': 0, 'medeleg': 0, 'mtvec': 0, 'stvec': 0, 'mepc': 0, 'sepc': 0, 'mcause': 0, 'scause': 0, 'mtval': 0, 'stval': 0, 'mscratch': 0, 'sscratch': 0, 'satp': 0}, {}, None, None, None] - -#with open (InputFile, 'r') as InputFileFP: -#lines = InputFileFP.readlines() -lineNum = 0 -StartLine = 0 -EndLine = 0 -numInstrs = 0 -#instructions = [] -MemAdr = 0 -lines = [] -interrupts=open(interruptFname,'w') -interrupts.close() - -prevInstrOutString='' -currInstrOutString='' -for line in fileinput.input('-'): - if line.startswith('riscv_cpu_do_interrupt'): - with open(interruptFname,'a') as interrupts: - # Write line - # Example line: hart:0, async:0, cause:0000000000000002, epc:0x0000000080008548, tval:0x0000000000000000, desc=illegal_instruction - interrupts.write(line) - # Write instruction count - interrupts.write(str(numInstrs)+'\n') - # Convert line to rows of info for easier Verilog parsing - vals=line.strip('riscv_cpu_do_interrupt: ').strip('\n').split(',') - vals=[val.split(':')[-1].strip(' ') for val in vals] - vals=[val.split('=')[-1].strip(' ') for val in vals] - for val in vals: - interrupts.write(val+'\n') - continue - lines.insert(lineNum, line) - if InstrStartDelim in line: - lineNum = 0 - StartLine = lineNum - elif InstrEndDelim in line: - EndLine = lineNum - (InstrBits, text) = lines[StartLine].split(':') - InstrBits = int(InstrBits.strip('=> '), 16) - text = text.strip() - PC = int(lines[StartLine+1].split(':')[0][2:], 16) - Regs = toDict(lines[StartLine+2:EndLine]) - (Class, Addr, WriteReg, ReadReg) = whichClass(text, Regs) - #print("CWR", Class, WriteReg, ReadReg) - PreviousInstr = CurrentInstr - - Changed = whatChanged(PreviousInstr[4], Regs) - - if (ReadReg !=None): ReadData = ReadReg - else: ReadData = None - - if (WriteReg !=None): WriteData = WriteReg - else: WriteData = None - - CurrentInstr = [PC, InstrBits, text, Class, Regs, Changed, Addr, WriteData, ReadData] - - #print(CurrentInstr[0:4], PreviousInstr[5], CurrentInstr[6:7], PreviousInstr[8]) - - # pc, instrbits, text and class come from the last line. - MoveInstrToRegWriteLst = PreviousInstr[0:4] - # updated registers come from the current line. - MoveInstrToRegWriteLst.append(CurrentInstr[5]) # destination regs - # memory address if present comes from the last line. - MoveInstrToRegWriteLst.append(PreviousInstr[6]) # MemAdrM - # write data from the previous line - #MoveInstrToRegWriteLst.append(PreviousInstr[7]) # WriteDataM - - if (PreviousInstr[7] != None): - MoveInstrToRegWriteLst.append(Regs[PreviousInstr[7]]) # WriteDataM - else: - MoveInstrToRegWriteLst.append(None) - - # read data from the current line - #MoveInstrToRegWriteLst.append(PreviousInstr[8]) # ReadDataM - if (PreviousInstr[8] != None): - MoveInstrToRegWriteLst.append(Regs[PreviousInstr[8]]) # ReadDataM - else: - MoveInstrToRegWriteLst.append(None) - - lines.clear() - #instructions.append(MoveInstrToRegWriteLst) - - prevInstrOutString = currInstrOutString - currInstrOutString = PrintInstr(MoveInstrToRegWriteLst) - # Remove duplicates - if (PreviousInstr[0] != CurrentInstr[0]) and (currInstrOutString != None): - sys.stdout.write(currInstrOutString) - numInstrs += 1 - if (numInstrs % 1e5 == 0): - sys.stderr.write('GDB trace parser reached '+str(numInstrs/1.0e6)+' million instrs.\n') - sys.stderr.flush() - lineNum += 1 - - -#for instruction in instructions[1::]: - - -#with open(OutputFile, 'w') as OutputFileFP: -# print('opened file') - - - diff --git a/linux/testvector-generation/parsePlicState.py b/linux/testvector-generation/parsePlicState.py deleted file mode 100755 index 5fb2b4eac..000000000 --- a/linux/testvector-generation/parsePlicState.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 -import sys, os -from functools import reduce - -################ -# Helper Funcs # -################ - -def tokenize(string): - tokens = [] - token = '' - whitespace = 0 - prevWhitespace = 0 - for char in string: - prevWhitespace = whitespace - whitespace = char in ' \t\n' - if (whitespace): - if ((not prevWhitespace) and (token != '')): - tokens.append(token) - token = '' - else: - token = token + char - return tokens - -def strip0x(num): - return num[2:] - -def stripZeroes(num): - num = int(num,16) - return hex(num)[2:] - -############# -# Main Code # -############# -print("Begin parsing PLIC state.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error parsePlicState.py expects 1 arg: ') -outDir = sys.argv[1]+'/' -rawPlicStateFile = outDir+'plicStateGDB.txt' -if not os.path.exists(rawPlicStateFile): - sys.exit('Error input file '+rawPlicStateFile+'not found') - -with open(rawPlicStateFile, 'r') as rawPlicStateFile: - plicIntPriorityArray = [] # iterates over number of different sources - # 0x0C000004 thru 0x0C000010 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000014 thru 0x0C000020 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000024 thru 0x0C000030 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000034 thru 0x0C000040 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000044 thru 0x0C000050 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000054 thru 0x0C000060 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000064 thru 0x0C000070 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000074 thru 0x0C000080 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000084 thru 0x0C000090 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000094 thru 0x0C0000a0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000a4 thru 0x0C0000b0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000b4 thru 0x0C0000c0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000c4 thru 0x0C0000d0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000d4 thru 0x0C0000e0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000e4 thru 0x0C0000f0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000f4 thru 0x0C0000fc - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - - plicIntEnableArray = [] # iterates over number of different contexts - # 0x0C020000 thru 0x0C020004 - plicIntEnable = tokenize(rawPlicStateFile.readline())[1:] - plicIntEnable = map(strip0x,plicIntEnable) - plicIntEnableArray.append(reduce(lambda x,y: y+x,plicIntEnable)) - # 0x0C020080 thru 0x0C020084 - plicIntEnable = tokenize(rawPlicStateFile.readline())[1:] - plicIntEnable = map(strip0x,plicIntEnable) - plicIntEnableArray.append(reduce(lambda x,y: y+x,plicIntEnable)) - - plicIntPriorityThresholdArray = [] # iterates over number of different contexts - # 0x0C200000 - plicIntPriorityThresholdArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C201000 - plicIntPriorityThresholdArray += tokenize(rawPlicStateFile.readline())[1:] - -with open(outDir+'checkpoint-PLIC_INT_PRIORITY', 'w') as outFile: - for word in plicIntPriorityArray: - outFile.write(stripZeroes(word[2:])+'\n') -with open(outDir+'checkpoint-PLIC_INT_ENABLE', 'w') as outFile: - for word in plicIntEnableArray: - outFile.write(stripZeroes(word[2:])+'\n') -with open(outDir+'checkpoint-PLIC_THRESHOLD', 'w') as outFile: - for word in plicIntPriorityThresholdArray: - outFile.write(stripZeroes(word[2:])+'\n') - -print("Finished parsing PLIC state!") diff --git a/linux/testvector-generation/parseQEMUtoGDB.py b/linux/testvector-generation/parseQEMUtoGDB.py deleted file mode 100755 index 457085a1b..000000000 --- a/linux/testvector-generation/parseQEMUtoGDB.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python3 -import fileinput, sys - -parseState = "idle" -beginPageFault = 0 -inPageFault = 0 -endPageFault = 0 -CSRs = {} -pageFaultCSRs = {} -regs = {} -pageFaultRegs = {} -instrs = {} -instrCount = 0 -returnAdr = 0 -sys.stderr.write("reminder: parse_qemu.py takes input from stdin\n") - -def printPC(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, instrCount - if not inPageFault: - inst = l.split() - if len(inst) > 3: - print(f'=> {inst[1]}:\t{inst[2]} {inst[3]}') - else: - print(f'=> {inst[1]}:\t{inst[2]}') - print(f'{inst[0]} 0x{inst[1]}') - instrCount += 1 - if ((instrCount % 100000) == 0): - sys.stderr.write("QEMU parser reached "+str(instrCount)+" instrs\n") - -def printCSRs(): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs - global interrupt_line - if not inPageFault: - for (csr,val) in CSRs.items(): - print('{}{}{:#x} {}'.format(csr, ' '*(15-len(csr)), val, val)) - print('-----') # end of current instruction - if len(interrupt_line)>0: # squish interrupts in between instructions - print(interrupt_line) - interrupt_line="" - -def parseCSRs(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs - if l.strip() and (not l.startswith("Disassembler")) and (not l.startswith("Please")): - # If we've hit the register file - if l.startswith(' x0/zero'): - parseState = "regFile" - if not inPageFault: - instr = instrs[CSRs["pc"]] - printPC(instr) - parseRegs(l) - # If we've hit a CSR - else: - csr = l.split()[0] - val = int(l.split()[1],16) - # Commented out this conditional because the pageFault instrs don't corrupt CSRs - #if inPageFault: - # Not sure if these CSRs should be updated or not during page fault. - #if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"): - # We do update some CSRs - # CSRs[csr] = val - #else: - # Others we preserve until changed later - # pageFaultCSRs[csr] = val - #elif pageFaultCSRs and (csr in pageFaultCSRs): - # if (val != pageFaultCSRs[csr]): - # del pageFaultCSRs[csr] - # CSRs[csr] = val - #else: - # CSRs[csr] = val - # - # However SEPC and STVAL do get corrupted upon exiting - if endPageFault and ((csr == 'sepc') or (csr == 'stval')): - CSRs[csr] = returnAdr - pageFaultCSRs[csr] = val - elif pageFaultCSRs and (csr in pageFaultCSRs): - if (val != pageFaultCSRs[csr]): - del pageFaultCSRs[csr] - CSRs[csr] = val - else: - CSRs[csr] = val - -def parseRegs(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, pageFaultRegs - if "pc" in l: - printCSRs() - # New non-disassembled instruction - parseState = "CSRs" - parseCSRs(l) - elif l.startswith('--------'): - # End of disassembled instruction - printCSRs() - parseState = "idle" - else: - s = l.split() - for i in range(0,len(s),2): - if '/' in s[i]: - reg = s[i].split('/')[1] - val = int(s[i+1], 16) - if inPageFault: - pageFaultRegs[reg] = val - else: - if pageFaultRegs and (reg in pageFaultRegs): - if (val != pageFaultRegs[reg]): - del pageFaultRegs[reg] - regs[reg] = val - else: - regs[reg] = val - val = regs[reg] - print('{}{}{:#x} {}'.format(reg, ' '*(15-len(reg)), val, val)) - else: - sys.stderr.write("Whoops. Expected a list of reg file regs; got:\n"+l) - -############# -# Main Code # -############# -interrupt_line="" -for l in fileinput.input(): - #sys.stderr.write(l) - if l.startswith('riscv_cpu_do_interrupt'): - sys.stderr.write(l) - interrupt_line = l.strip('\n') - elif l.startswith('qemu-system-riscv64: QEMU: Terminated via GDBstub'): - break - elif l.startswith('IN:'): - # New disassembled instr - parseState = "instr" - elif (parseState == "instr") and l.startswith('0x'): - # New instruction - if "out of bounds" in l: - sys.stderr.write("Detected QEMU page fault error\n") - beginPageFault = not inPageFault - if beginPageFault: - returnAdr = int(l.split()[0][2:-1], 16) - sys.stderr.write('Saving SEPC of '+hex(returnAdr)+'\n') - inPageFault = 1 - else: - endPageFault = inPageFault - inPageFault = 0 - adr = int(l.split()[0][2:-1], 16) - instrs[adr] = l - parseState = "CSRs" - elif parseState == "CSRs": - parseCSRs(l) - elif parseState == "regFile": - parseRegs(l) diff --git a/linux/testvector-generation/parseState.py b/linux/testvector-generation/parseState.py deleted file mode 100755 index f54ba0f78..000000000 --- a/linux/testvector-generation/parseState.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -import sys, os - -################ -# Helper Funcs # -################ - -def tokenize(string): - tokens = [] - token = '' - whitespace = 0 - prevWhitespace = 0 - for char in string: - prevWhitespace = whitespace - whitespace = char in ' \t\n' - if (whitespace): - if ((not prevWhitespace) and (token != '')): - tokens.append(token) - token = '' - else: - token = token + char - return tokens - -############# -# Main Code # -############# -print("Begin parsing CPU state.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error parseState.py expects 1 arg:\n parseState.py ') -outDir = sys.argv[1]+'/' -stateGDBpath = outDir+'stateGDB.txt' -if not os.path.exists(stateGDBpath): - sys.exit('Error input file '+stateGDBpath+'not found') - -singleCSRs = ['pc','mip','mie','mscratch','mcause','mepc','mtvec','medeleg','mideleg','sscratch','scause','sepc','stvec','sedeleg','sideleg','satp','mstatus','priv','sie','sip','sstatus'] -# priv (current privilege mode) isn't technically a CSR but we can log it with the same machinery -thirtyTwoBitCSRs = ['mcounteren','scounteren'] -listCSRs = ['hpmcounter','pmpaddr'] -pmpcfg = ['pmpcfg'] - -# Initialize List CSR files to empty -# (because later we'll open them in append mode) -for csr in listCSRs+pmpcfg: - outFileName = 'checkpoint-'+csr.upper() - outFile = open(outDir+outFileName, 'w') - outFile.close() - -# Initial State for Main Loop -currState = 'regFile' -regFileIndex = 0 -outFileName = 'checkpoint-RF' -outFile = open(outDir+outFileName, 'w') - -# Main Loop -with open(stateGDBpath, 'r') as stateGDB: - for line in stateGDB: - line = tokenize(line) - name = line[0] - val = line[1][2:] - if (currState == 'regFile'): - if (regFileIndex == 0 and name != 'zero'): - print('Whoops! Expected regFile registers to come first, starting with zero') - exit(1) - if (name != 'zero'): - # Wally doesn't need to know zero=0 - outFile.write(val+'\n') - regFileIndex += 1 - if (regFileIndex == 32): - outFile.close() - currState = 'CSRs' - elif (currState == 'CSRs'): - if name in singleCSRs: - outFileName = 'checkpoint-'+name.upper() - outFile = open(outDir+outFileName, 'w') - outFile.write(val+'\n') - outFile.close() - elif name in thirtyTwoBitCSRs: - outFileName = 'checkpoint-'+name.upper() - outFile = open(outDir+outFileName, 'w') - val = int(val,16) & 0xffffffff - outFile.write(hex(val)[2:]+'\n') - outFile.close() - elif name.strip('0123456789') in listCSRs: - outFileName = 'checkpoint-'+name.upper().strip('0123456789') - outFile = open(outDir+outFileName, 'a') - outFile.write(val+'\n') - outFile.close() - elif name.strip('0123456789') in pmpcfg: - outFileName = 'checkpoint-'+name.upper().strip('0123456789') - outFile = open(outDir+outFileName, 'a') - fourPmp = int(val,16) - for i in range(0,4): - byte = (fourPmp >> 8*i) & 0xff - outFile.write(hex(byte)[2:]+'\n') - outFile.close() - -print("Finished parsing CPU state!") diff --git a/linux/testvector-generation/parseUartState.py b/linux/testvector-generation/parseUartState.py deleted file mode 100755 index 82028d528..000000000 --- a/linux/testvector-generation/parseUartState.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -import sys, os - -################ -# Helper Funcs # -################ - -def tokenize(string): - tokens = [] - token = '' - whitespace = 0 - prevWhitespace = 0 - for char in string: - prevWhitespace = whitespace - whitespace = char in ' \t\n' - if (whitespace): - if ((not prevWhitespace) and (token != '')): - tokens.append(token) - token = '' - else: - token = token + char - return tokens - -############# -# Main Code # -############# -print("Begin parsing UART state.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error parseUartState.py expects 1 arg: ') -outDir = sys.argv[1]+'/' -rawUartStateFile = outDir+'uartStateGDB.txt' -if not os.path.exists(rawUartStateFile): - sys.exit('Error input file '+rawUartStateFile+'not found') - -with open(rawUartStateFile, 'r') as rawUartStateFile: - uartBytes = [] - for i in range(0,8): - uartBytes += tokenize(rawUartStateFile.readline())[1:] -with open(outDir+'checkpoint-UART_IER', 'w') as outFile: - outFile.write(uartBytes[1][2:]) -with open(outDir+'checkpoint-UART_LCR', 'w') as outFile: - outFile.write(uartBytes[3][2:]) -with open(outDir+'checkpoint-UART_MCR', 'w') as outFile: - outFile.write(uartBytes[4][2:]) -with open(outDir+'checkpoint-UART_SCR', 'w') as outFile: - outFile.write(uartBytes[7][2:]) - -print("Finished parsing UART state!") From 4a606de9106d7a06d8d60616e4130870dc39542f Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Mon, 4 Nov 2024 09:49:12 -0600 Subject: [PATCH 38/42] Parallelized objdump and memfile gen. --- tests/riscof/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/riscof/Makefile b/tests/riscof/Makefile index 131d724c4..e5f36c0a3 100644 --- a/tests/riscof/Makefile +++ b/tests/riscof/Makefile @@ -31,7 +31,7 @@ arch%: config$$*.ini | $(work_dir) $(arch_workdir) # Generate wally-riscv-arch-test targets wally%: config$$*.ini | $(work_dir) $(wally_workdir) riscof run --work-dir=$(work_dir)/$@ --config=$< --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run - $(MAKE) -f makefile-memfile WORKDIR=$(work_dir)/$@ + $(MAKE) -f makefile-memfile --jobs WORKDIR=$(work_dir)/$@ rsync -a $(work_dir)/$@/rv*/* $(wally_workdir)/rv$(patsubst %64,%64i,$(patsubst %32,%32i,$*))_m || echo "error suppressed" quad64: config64.ini $(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests | $(work_dir) From d769d47088f1fed3681c311aeea1402cae73cba6 Mon Sep 17 00:00:00 2001 From: Rose Thompson Date: Mon, 4 Nov 2024 10:15:12 -0600 Subject: [PATCH 39/42] Revert "Parallelized objdump and memfile gen." This reverts commit 4a606de9106d7a06d8d60616e4130870dc39542f. --- tests/riscof/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/riscof/Makefile b/tests/riscof/Makefile index e5f36c0a3..131d724c4 100644 --- a/tests/riscof/Makefile +++ b/tests/riscof/Makefile @@ -31,7 +31,7 @@ arch%: config$$*.ini | $(work_dir) $(arch_workdir) # Generate wally-riscv-arch-test targets wally%: config$$*.ini | $(work_dir) $(wally_workdir) riscof run --work-dir=$(work_dir)/$@ --config=$< --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run - $(MAKE) -f makefile-memfile --jobs WORKDIR=$(work_dir)/$@ + $(MAKE) -f makefile-memfile WORKDIR=$(work_dir)/$@ rsync -a $(work_dir)/$@/rv*/* $(wally_workdir)/rv$(patsubst %64,%64i,$(patsubst %32,%32i,$*))_m || echo "error suppressed" quad64: config64.ini $(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests | $(work_dir) From 120b21d7d5482a3b56a5d7073ff6a21cea8dd2e5 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 4 Nov 2024 15:38:12 -0600 Subject: [PATCH 40/42] More SPI optimizations. --- src/uncore/spi_apb.sv | 85 ++++++++++++++++-------------------- src/uncore/spi_controller.sv | 24 +++------- 2 files changed, 43 insertions(+), 66 deletions(-) diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 38fa07f42..9b15839e7 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -48,7 +48,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( output logic SPICLK ); - // register map + // register map localparam SPI_SCKDIV = 8'h00; localparam SPI_SCKMODE = 8'h04; localparam SPI_CSID = 8'h10; @@ -89,7 +89,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic InactiveState; logic [3:0] FrameLength; - // + // Starting Transmission and restarting SCLKenable logic ResetSCLKenable; logic TransmitStart; logic TransmitStartD; @@ -98,15 +98,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( typedef enum logic [1:0] {READY, START, WAIT} txState; txState CurrState, NextState; - // FIFO FSM signals - // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] - logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + // FIFO Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] + logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + + // Transmit FIFO Signals logic TransmitFIFOFull, TransmitFIFOEmpty; logic TransmitFIFOWriteInc; logic TransmitFIFOReadInc; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read logic [7:0] TransmitReadData; - // + // ReceiveFIFO Signals logic ReceiveFIFOWriteInc; logic ReceiveFIFOReadInc; logic ReceiveFIFOFull, ReceiveFIFOEmpty; @@ -137,7 +138,6 @@ 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 - // assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP; assign PREADY = 1'b1; // Account for subword read/write circuitry @@ -164,7 +164,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( InterruptEnable <= 2'b0; InterruptPending <= 2'b0; end else begin // writes - /* verilator lint_off CASEINCOMPLETE */ + /* verilator lint_off CASEINCOMPLETE */ if (Memwrite) case(Entry) // flop to sample inputs SPI_SCKDIV: SckDiv <= Din[11:0]; @@ -217,7 +217,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( spi_controller controller(PCLK, PRESETn, // Transmit Signals - TransmitStart, TransmitStartD, ResetSCLKenable, + TransmitStart, TransmitRegLoaded, ResetSCLKenable, // Register Inputs SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff @@ -230,23 +230,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( SPICLK); // Transmit FIFO --------------------------------------------------- - + // txFIFO write increment logic - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOWriteInc <= 1'b0; - end else begin - TransmitFIFOWriteInc <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull); - end + flopr #(1) txwincreg(PCLK, ~PRESETn, + (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull), + TransmitFIFOWriteInc); // txFIFO read increment logic - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOReadInc <= 1'b0; - end else if (SCLKenable) begin - TransmitFIFOReadInc <= TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty) ; - end - + flopenr #(1) txrincreg(PCLK, ~PRESETn, SCLKenable, + TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty), + TransmitFIFOReadInc); + // Check whether TransmitReg has been loaded. // We use this signal to prevent returning to the Ready state for TransmitStart always_ff @(posedge PCLK) begin @@ -258,15 +252,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( TransmitRegLoaded <= 1'b0; end end - + // Setup TransmitStart state machine - always_ff @(posedge PCLK) begin - if (~PRESETn) begin - CurrState <= READY; - end else begin - CurrState <= NextState; - end - end + always_ff @(posedge PCLK) + if (~PRESETn) CurrState <= READY; + else CurrState <= NextState; // State machine for starting transmissions always_comb begin @@ -280,12 +270,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase end + // Delayed TransmitStart signal for incrementing tx read point. assign TransmitStart = (CurrState == START); always_ff @(posedge PCLK) if (~PRESETn) TransmitStartD <= 1'b0; else if (TransmitStart) TransmitStartD <= 1'b1; else if (SCLKenable) TransmitStartD <= 1'b0; - + + // Transmit FIFO spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteInc, TransmitFIFOReadInc, TransmitData[7:0], @@ -296,20 +288,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( TransmitWriteMark, TransmitReadMark); // Receive FIFO ---------------------------------------------------- - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOReadInc <= 1'b0; - end else begin - ReceiveFIFOReadInc <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc); - end - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOWriteInc <= 1'b0; - end else if (SCLKenable) begin - ReceiveFIFOWriteInc <= EndOfFrame; - end - + // Receive FIFO Read Increment register + flopr #(1) rxfiforincreg(PCLK, ~PRESETn, + ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc), + ReceiveFIFOReadInc); + + // Receive FIFO Write Increment register + flopenr #(1) rxfifowincreg(PCLK, ~PRESETn, SCLKenable, + EndOfFrame, ReceiveFIFOWriteInc); + + // Receive FIFO spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveFIFOWriteInc, ReceiveFIFOReadInc, ReceiveShiftRegEndian, ReceiveWatermark[2:0], @@ -319,6 +308,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( ReceiveFIFOEmpty, ReceiveWriteMark, ReceiveReadMark); + // Shift Registers -------------------------------------------------- // Transmit shift register assign TransmitLoad = TransmitStart | (EndOfFrame & ~TransmitFIFOEmpty); assign TransmitDataEndian = Format[0] ? {<<{TransmitReadData[7:0]}} : TransmitReadData[7:0]; @@ -340,12 +330,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if(~PRESETn) begin ReceiveShiftReg <= 8'b0; end else if (SampleEdge) begin - if (~Transmitting) ReceiveShiftReg <= 8'b0; - else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; + ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; end // Aligns received data and reverses if little-endian - assign LeftShiftAmount = 4'h8 - Format[4:1]; + assign LeftShiftAmount = 4'h8 - FrameLength; assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0]; assign ReceiveShiftRegEndian = Format[0] ? {<<{ASR[7:0]}} : ASR[7:0]; diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 0400d2956..475f9c1c9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -33,7 +33,7 @@ module spi_controller ( // Start Transmission input logic TransmitStart, - input logic TransmitStartD, + input logic TransmitRegLoaded, input logic ResetSCLKenable, // Registers @@ -84,7 +84,7 @@ module spi_controller ( // Transmit Stuff logic ContinueTransmit; logic EndTransmission; - logic ContinueTransmitD; // TODO: Could be replaced by TransmitRegLoaded? + // logic TransmitRegLoaded; // TODO: Could be replaced by TransmitRegLoaded? logic NextEndDelay; logic CurrentEndDelay; @@ -151,8 +151,7 @@ module spi_controller ( BitNum <= 4'h0; DelayCounter <= 0; end else begin - // TODO: Consolidate into one delay counter since none of the - // delays happen at the same time? + // SCK logic for delay times if (TransmitStart) begin SCK <= 0; end else if (SCLKenable) begin @@ -242,17 +241,6 @@ module spi_controller ( // Logic for continuing to transmit through Delay states after end of frame assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR; assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR; - - // - always_ff @(posedge PCLK) begin - if (~PRESETn) begin - ContinueTransmitD <= 1'b0; - end else if (NextEndDelay & ~CurrentEndDelay) begin - ContinueTransmitD <= ContinueTransmit; - end else if (EndOfSCKCS & SCLKenable) begin - ContinueTransmitD <= 1'b0; - end - end always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -264,7 +252,7 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: if (TransmitStartD) begin + INACTIVE: if (TransmitRegLoaded) begin if (~HasCSSCK) NextState = TRANSMIT; else NextState = CSSCK; end else begin @@ -294,7 +282,7 @@ module spi_controller ( end SCKCS: begin // SCKCS case -------------------------------------- if (EndOfSCKCS) begin - if (~ContinueTransmitD) begin + if (~TransmitRegLoaded) begin // if (CSMode == AUTOMODE) NextState = INACTIVE; if (CSMode == HOLDMODE) NextState = HOLD; else NextState = INACTIVE; @@ -309,7 +297,7 @@ module spi_controller ( HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin NextState = INACTIVE; - end else if (TransmitStartD) begin // If FIFO is written to, start again. + end else if (TransmitRegLoaded) begin // If FIFO is written to, start again. NextState = TRANSMIT; end else NextState = HOLD; end From 507c1dad1ce614934743776918d9149f2097f7ba Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 4 Nov 2024 16:15:42 -0600 Subject: [PATCH 41/42] Removed impossible condition in receive register logic. --- src/uncore/spi_controller.sv | 6 +++--- src/uncore/spi_fifo.sv | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 475f9c1c9..37c1e3ac9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -45,7 +45,7 @@ module spi_controller ( input logic [3:0] FrameLength, // Is the Transmit FIFO Empty? - input logic txFIFOReadEmpty, + input logic TransmitFIFOEmpty, // Control signals output logic SCLKenable, @@ -140,8 +140,8 @@ module spi_controller ( // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase assign SCLKenable = DivCounter == SckDiv; - assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame; - assign EndTransmission = txFIFOReadEmpty & EndOfFrame; + assign ContinueTransmit = ~TransmitFIFOEmpty & EndOfFrame; + assign EndTransmission = TransmitFIFOEmpty & EndOfFrame; always_ff @(posedge PCLK) begin if (~PRESETn) begin diff --git a/src/uncore/spi_fifo.sv b/src/uncore/spi_fifo.sv index 40c3ca4ff..1e4910faf 100644 --- a/src/uncore/spi_fifo.sv +++ b/src/uncore/spi_fifo.sv @@ -19,6 +19,10 @@ module spi_fifo #(parameter M=3, N=8)( // 2^M entries of N bits logic [M:0] rptrnext, wptrnext; logic [M-1:0] raddr; logic [M-1:0] waddr; + + logic [M-1:0] numVals; + + assign numVals = waddr - raddr; assign rdata = mem[raddr]; always_ff @(posedge PCLK) From 4e2b3cdbec88d2a5777fd5482fc8461bd3e540b0 Mon Sep 17 00:00:00 2001 From: slmnemo Date: Sun, 3 Nov 2024 21:33:29 -0800 Subject: [PATCH 42/42] Removed symlinks for non-buildroot derivative configs --- bin/derivgen.pl | 18 ++++++++++-------- bin/wsim | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/bin/derivgen.pl b/bin/derivgen.pl index 5dee10243..8a065bf7e 100755 --- a/bin/derivgen.pl +++ b/bin/derivgen.pl @@ -88,14 +88,16 @@ foreach my $key (@derivnames) { open(my $unmod, $configunmod) or die "Could not open file '$configunmod' $!"; open(my $fh, '>>', $config) or die "Could not open file '$config' $!"; - # Create symlink to imperas.ic for deriv if exists - my $baseimperas_ic = "$ENV{WALLY}/config/$basederiv{$key}/imperas.ic"; - if (! -e $baseimperas_ic) { - my $baseimperas_ic = "$ENV{WALLY}/config/deriv/$basederiv{$key}/config.vh"; - } - if (-e $baseimperas_ic) { # If imperas.ic exists for base derivative, create hardlink to it - my $imperas_ic = "$dir/imperas.ic"; - system("ln -T $baseimperas_ic $imperas_ic"); + # Create symlink to imperas.ic for deriv buildroot + if ($key eq "buildroot") { + my $baseimperas_ic = "$ENV{WALLY}/config/$basederiv{$key}/imperas.ic"; + if (! -e $baseimperas_ic) { + my $baseimperas_ic = "$ENV{WALLY}/config/deriv/$basederiv{$key}/config.vh"; + } + if (-e $baseimperas_ic) { # If imperas.ic exists for base derivative, create hardlink to it + my $imperas_ic = "$dir/imperas.ic"; + system("ln -T $baseimperas_ic $imperas_ic"); + } } my $datestring = localtime(); diff --git a/bin/wsim b/bin/wsim index dde022bed..d930277ec 100755 --- a/bin/wsim +++ b/bin/wsim @@ -90,7 +90,7 @@ else: EnableLog = 0 prefix = "" if (args.lockstep or args.lockstepverbose or args.fcov or args.fcovimp): if (args.sim == "questa" or args.sim == "vcs"): - prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic" + prefix = "IMPERAS_TOOLS=" + os.path.join(WALLY, "config", args.config, "imperas.ic") if not os.path.isfile(prefix): # If config is a derivative, look for imperas.ic in derivative configs prefix = "IMPERAS_TOOLS=" + os.path.join(WALLY, "config", "deriv", args.config, "imperas.ic") # Force Questa to use 64-bit mode, sometimes it defaults to 32-bit even on 64-bit machines