From a767c15ae488bd333dee9561f825049458eb324a Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Wed, 28 Feb 2024 10:55:30 -0600 Subject: [PATCH 01/20] uncore: Add bsg_dmc memory controller to AHB bus --- src/uncore/uncore.sv | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 22e0a35fc..48e87fe2b 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -63,15 +63,17 @@ module uncore import cvw::*; #(parameter cvw_t P)( logic [P.XLEN-1:0] HREADRam, HREADSDC; - logic [11:0] HSELRegions; + logic [12:0] HSELRegions; logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSPI; logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID; logic HRESPRam, HRESPSDC; logic HREADYRam, HRESPSDCD; - logic [P.XLEN-1:0] HREADBootRom; + logic [P.XLEN-1:0] HREADBootRom; logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC; + logic [P.XLEN-1:0] HREADBsgDmc; + logic HSELBsgDmc, HSELBsgDmcD, HRESPBsgDmc, HREADYBsgDmc; logic HSELNoneD; - logic UARTIntr,GPIOIntr, SPIIntr; + logic UARTIntr, GPIOIntr, SPIIntr; logic SDCIntM; logic PCLK, PRESETn, PWRITE, PENABLE; @@ -92,7 +94,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1]; + assign {HSELBsgDmc, HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[12:1]; // AHB -> APB bridge ahbapbbridge #(P, 5) ahbapbbridge ( @@ -158,30 +160,38 @@ module uncore import cvw::*; #(parameter cvw_t P)( assign SPIOut = 0; assign SPICS = 0; assign SPIIntr = 0; end + // FIXME: Do we need to block this off in an if (like SPI above)? + bsg_dmc_ahb #(P.PA_BITS, P.XLEN) external_ram ( + .HCLK, .HRESETn, .HSEL(HSELBsgDmc), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, + .HRDATA(HREADBsgDmc), .HRESP(HRESPBsgDmc), .HREADYOUT(HREADYBsgDmc)); + // AHB Read Multiplexer assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) | - ({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) | + ({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) | ({P.XLEN{HSELBRIDGED}} & HREADBRIDGE) | - ({P.XLEN{HSELBootRomD}} & HREADBootRom); + ({P.XLEN{HSELBootRomD}} & HREADBootRom) | + ({P.XLEN{HSELBsgDmcD}} & HREADBsgDmc); assign HRESP = HSELRamD & HRESPRam | (HSELEXTD | HSELEXTSDCD) & HRESPEXT | HSELBRIDGE & HRESPBRIDGE | - HSELBootRomD & HRESPBootRom; + HSELBootRomD & HRESPBootRom | + HSELBsgDmcD & HRESPBsgDmc; assign HREADY = HSELRamD & HREADYRam | - (HSELEXTD | HSELEXTSDCD) & HREADYEXT | + (HSELEXTD | HSELEXTSDCD) & HREADYEXT | HSELBRIDGED & HREADYBRIDGE | HSELBootRomD & HREADYBootRom | + HSELBsgDmcD & HREADYBsgDmc | HSELNoneD; // don't lock up the bus if no region is being accessed // Address Decoder Delay (figure 4-2 in spec) // The select for HREADY needs to be based on the address phase address. If the device // takes more than 1 cycle to repsond it needs to hold on to the old select until the - // device is ready. Hense this register must be selectively enabled by HREADY. - // However on reset None must be seleted. - flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1, - {HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD, - HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD}); + // device is ready. Hence this register must be selectively enabled by HREADY. + // However on reset None must be selected. + flopenl #(13) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 13'b1, + {HSELBsgDmcD, HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, + HSELCLINTD, HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD}); flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED); endmodule From 0932f458eecdcab35c15228e2541f36e6ce19cb7 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Wed, 28 Feb 2024 15:47:18 -0600 Subject: [PATCH 02/20] uncore: Add bsg_dmc and expose DDR PHY interface --- .gitmodules | 3 + src/uncore/ahbxuiconverter.sv | 114 +++++++++++++++++++++++ src/uncore/basejump_stl | 1 + src/uncore/bsg_dmc_ahb.sv | 164 ++++++++++++++++++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 src/uncore/ahbxuiconverter.sv create mode 160000 src/uncore/basejump_stl create mode 100644 src/uncore/bsg_dmc_ahb.sv diff --git a/.gitmodules b/.gitmodules index 4717e75eb..4be9799dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,6 @@ [submodule "addins/ahbsdc"] path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git +[submodule "src/uncore/basejump_stl"] + path = src/uncore/basejump_stl + url = https://github.com/bespoke-silicon-group/basejump_stl diff --git a/src/uncore/ahbxuiconverter.sv b/src/uncore/ahbxuiconverter.sv new file mode 100644 index 000000000..cb607889b --- /dev/null +++ b/src/uncore/ahbxuiconverter.sv @@ -0,0 +1,114 @@ +/////////////////////////////////////////// +// ahbxuiconverter.sv +// +// Written: infinitymdm@gmail.com +// +// Purpose: AHB to Xilinx UI converter +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module ahbxuiconverter #(parameter ADDR_SIZE = 31, + parameter DATA_SIZE = 64) ( + // AHB signals + input logic HCLK, + input logic HRESETn, + input logic HSEL, + input logic [ADDR_SIZE-1:0] HADDR, + input logic [DATA_SIZE-1:0] HWDATA, + input logic [DATA_SIZE/8-1:0] HWSTRB, + input logic HWRITE, + input logic [1:0] HTRANS, + input logic HREADY, + output logic [DATA_SIZE-1:0] HRDATA, + output logic HRESP, + output logic HREADYOUT, + + // UI signals + output logic sys_reset, + input logic ui_clk, // from PLL + input logic ui_clk_sync_rst, + output logic [ADDR_SIZE-1:0] app_addr, // Double check this width + output logic [2:0] app_cmd, + output logic app_en, + input logic app_rdy, + output logic app_wdf_wren, + output logic [DATA_SIZE-1:0] app_wdf_data, + output logic [DATA_SIZE/8-1:0] app_wdf_mask, + output logic app_wdf_end, + input logic app_wdf_rdy, + input logic [DATA_SIZE-1:0] app_rd_data, + input logic app_rd_data_end, + input logic app_rd_data_valid, + input logic init_calib_complete +); + + assign sys_reset = ~HRESETn; + + // Enable this peripheral when: + // a) selected, AND + // b) a transfer is started, AND + // c) the bus is ready + logic ahbEnable; + assign ahbEnable = HSEL & HTRANS[1] & HREADY; + + // UI is ready for a command when initialized and ready to read and write + logic uiReady; + assign uiReady = app_rdy & app_wdf_rdy & init_calib_complete; + + // Buffer the input down to ui_clk speed + logic [ADDR_SIZE-1:0] addr; + logic [DATA_SIZE-1:0] data; + logic [DATA_SIZE/8-1:0] mask; + logic cmdEnable, cmdWrite; + logic cmdwfull, cmdrempty; + // FIFO needs addr + (data + mask) + (enable + write) + fifo #(ADDR_SIZE + 9*DATA_SIZE/8 + 2, 32) cmdfifo ( + .wdata({HADDR, HWDATA, HWSTRB, ahbEnable, HWRITE}), + .winc(ahbEnable), .wclk(HCLK), .wrst_n(HRESETn), + .rinc(uiReady), .rclk(ui_clk), .rrst_n(~ui_clk_sync_rst), + .rdata({addr, data, mask, cmdEnable, cmdWrite}), + .wfull(cmdwfull), .rempty(cmdrempty) + ); + + // Delay transactions 1 clk so we can set wren on the cycle after write commands + flopen #(ADDR_SIZE) addrreg (ui_clk, uiReady, addr, app_addr); + flopenr #(3) cmdreg (ui_clk, ui_clk_sync_rst, uiReady, {2'b0, ~cmdWrite}, app_cmd); + flopenr #(1) cmdenreg (ui_clk, ui_clk_sync_rst, uiReady, cmdEnable, app_en); + flopenr #(1) wrenreg (ui_clk, ui_clk_sync_rst, uiReady, ~app_cmd[0], app_wdf_wren); + flopenr #(DATA_SIZE) datareg (ui_clk, ui_clk_sync_rst, uiReady, data, app_wdf_data); + flopenr #(DATA_SIZE/8) maskreg (ui_clk, ui_clk_sync_rst, uiReady, mask, app_wdf_mask); + assign app_wdf_end = app_wdf_wren; // Since AHB will always put data on the bus after a write cmd, this is always valid + + // Return read data at HCLK speed TODO: Double check that rinc is correct + logic respwfull, resprempty; + fifo #(DATA_SIZE, 16) respfifo ( + .wdata(app_rd_data), + .winc(app_rd_data_valid), .wclk(ui_clk), .wrst_n(~ui_clk_sync_rst), + .rinc(ahbEnable), .rclk(HCLK), .rrst_n(HRESETn), + .rdata(HRDATA), + .wfull(respwfull), .rempty(resprempty) + ); + + assign HRESP = 0; // do not indicate errors + assign HREADYOUT = uiReady & ~cmdwfull; // TODO: Double check + +endmodule diff --git a/src/uncore/basejump_stl b/src/uncore/basejump_stl new file mode 160000 index 000000000..14f29e4d8 --- /dev/null +++ b/src/uncore/basejump_stl @@ -0,0 +1 @@ +Subproject commit 14f29e4d8a498ad62ec05fe232407f9d887e36a9 diff --git a/src/uncore/bsg_dmc_ahb.sv b/src/uncore/bsg_dmc_ahb.sv new file mode 100644 index 000000000..83de36b86 --- /dev/null +++ b/src/uncore/bsg_dmc_ahb.sv @@ -0,0 +1,164 @@ +/////////////////////////////////////////// +// bsg_dmc_ahb.sv +// +// Written: infinitymdm@gmail.com +// +// Purpose: BSG controller and LPDDRDRAM presenting an AHB interface +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "bsg_dmc.svh" + +module bsg_dmc_ahb + import bsg_tag_pkg::*; + import bsg_dmc_pkg::*; +#( + parameter ADDR_SIZE = 28, + parameter DATA_SIZE = 64, + parameter BURST_LENGTH = 8, + parameter FIFO_DEPTH = 4, +) ( + input logic HCLK, HRESETn, + input logic HSEL, + input logic [ADDR_SIZE-1:0] HADDR, + input logic [DATA_SIZE-1:0] HWDATA, + input logic [DATA_SIZE/8-1:0] HWSTRB, + input logic HWRITE, + input logic [1:0] HTRANS, + input logic HREADY, + output logic [DATA_SIZE-1:0] HRDATA, + output logic HRESP, HREADYOUT, + //input logic ui_clk // Add this once PLL is integrated + output logic ddr_ck_p, ddr_ck_n, ddr_cke, + output logic [2:0] ddr_ba, + output logic [15:0] ddr_addr, + output logic ddr_cs, ddr_ras, ddr_cas, + output logic ddr_we, ddr_reset, ddr_odt, + output logic [DATA_SIZE/16-1:0] ddr_dm_oen, ddr_dm, + output logic [DATA_SIZE/16-1:0] ddr_dqs_p_oen, ddr_dqs_p_ien, ddr_dqs_p_out, + input logic [DATA_SIZE/16-1:0] ddr_dqs_p_in, + output logic [DATA_SIZE/16-1:0] ddr_dqs_n_oen, ddr_dqs_n_ien, ddr_dqs_n_out, + input logic [DATA_SIZE/16-1:0] ddr_dqs_n_in, + output logic [DATA_SIZE/2-1:0] ddr_dq_oen, ddr_dq_out, + input logic [DATA_SIZE/2-1:0] ddr_dq_in, + input logic dfi_clk_2x, + output logic dfi_clk_1x +); + + localparam BURST_DATA_SIZE = DATA_SIZE * BURST_LENGTH; + // localparam DQ_DATA_SIZE = DATA_SIZE >> 1; + + // Global async reset + logic sys_reset; + + // Memory controller config + bsg_tag_s dmc_rst_tag, dmc_ds_tag; + bsg_tag_s [3:0] dmc_dly_tag, dmc_dly_trigger_tag; + bsg_dmc_s dmc_config; + + // UI signals + logic ui_clk_sync_rst; + logic [ADDR_SIZE-1:0] app_addr; + logic [2:0] app_cmd; + logic app_en, app_rdy, app_wdf_wren; + logic [DATA_SIZE-1:0] app_wdf_data; + logic [DATA_SIZE/8-1:0] app_wdf_mask; + logic app_wdf_end, app_wdf_rdy; + logic [DATA_SIZE-1:0] app_rd_data; + logic app_rd_data_end, app_rd_data_valid; + logic app_ref_ack, app_zq_ack, app_sr_active; // Sink unused UI signals + logic init_calib_complete; + logic [11:0] device_temp; // Reserved + + // Use a /6 clock divider until PLL is integrated. TODO: Replace + logic ui_clk; + integer clk_counter = 0; + always @(posedge HCLK) begin + counter <= counter + 1; + if (counter >= 6) counter <= 0; + ui_clk <= (counter >= 3); + end + + // TODO: Figure out how to initialize dmc_config correctly + always_comb begin: bsg_dmc_config + dmc_p.trefi = 1023; + dmc_p.tmrd = 1; + dmc_p.trfc = 15; + dmc_p.trc = 10; + dmc_p.trp = 2; + dmc_p.tras = 7; + dmc_p.trrd = 1; + dmc_p.trcd = 2; + dmc_p.twr = 10; + dmc_p.twtr = 7; + dmc_p.trtp = 10; + dmc_p.tcas = 3; + dmc_p.col_width = 11; + dmc_p.row_width = 14; + dmc_p.bank_width = 2; + dmc_p.dqs_sel_cal = 3; + dmc_p.init_cycles = 40010; + dmc_p.bank_pos = 25; + end + + ahbxuiconverter #(ADDR_SIZE, DATA_SIZE) bsg_dmc_ahb_ui_converter ( + .HCLK, .HRESETn, .HSEL, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA, .HRESP, .HREADYOUT, + .sys_reset, .ui_clk, .ui_clk_sync_rst, + .app_addr, .app_cmd, .app_en, .app_rdy, + .app_wdf_wren, .app_wdf_data, .app_wdf_mask, .app_wdf_end, .app_wdf_rdy, + .app_rd_data, .app_rd_data_end, .app_rd_data_valid, + .init_calib_complete + ); + + bsg_dmc #( + .num_adgs_p(1), + .ui_addr_width_p(ADDR_SIZE), + .ui_data_width_p(DATA_SIZE), + .burst_data_width_p(BURST_DATA_SIZE), + .dq_data_width_p(DQ_DATA_SIZE), + .cmd_afifo_depth(FIFO_DEPTH), + .cmd_sfifo_depth(FIFO_DEPTH) + ) dmc ( + .async_reset_tag_i(dmc_rst_tag), + .bsg_dly_tag_i(dmc_dly_tag), .bsg_dly_trigger_tag_i(dmc_dly_trigger_tag), .bsg_ds_tag_i(dmc_ds_tag), + .dmc_p_i(dmc_config), + .sys_reset_i(sys_reset), + .app_addr_i(app_addr), .app_cmd_i(app_cmd), .app_en_i(app_en), .app_rdy_o(app_rdy), + .app_wdf_wren_i(app_wdf_wren), .app_wdf_data_i(app_wdf_data), .app_wdf_mask_i(app_wdf_mask), .app_wdf_end_i(app_wdf_end), .app_wdf_rdy_o(app_wdf_rdy), + .app_rd_data_valid_o(app_rd_data_valid), .app_rd_data_o(app_rd_data), .app_rd_data_end_o(app_rd_data_end), + .app_ref_req_i(1'b0), .app_ref_ack_o(app_ref_ack), + .app_zq_req_i(1'b0), .app_zq_ack_o(app_zq_ack), + .app_sr_req_i(1'b0), .app_sr_active_o(app_sr_active), + .init_calib_complete_o(init_calib_complete), + .ddr_ck_p_o(ddr_ck_p), .ddr_ck_n_o(ddr_ck_n), .ddr_cke_o(ddr_cke), + .ddr_ba_o(ddr_ba), .ddr_addr_o(ddr_addr), .ddr_cs_n_o(ddr_cs), .ddr_ras_n_o(ddr_ras), .ddr_cas_n_o(ddr_cas), + .ddr_we_n_o(ddr_we), .ddr_reset_n_o(ddr_reset), .ddr_odt_o(ddr_odt), + .ddr_dm_oen_o(ddr_dm_oen), .ddr_dm_o(ddr_dm), + .ddr_dqs_p_oen_o(ddr_dqs_p_oen), .ddr_dqs_p_ien_o(ddr_dqs_p_ien), .ddr_dqs_p_o(ddr_dqs_p_out), .ddr_dqs_p_i(ddr_dqs_p_in), + .ddr_dqs_n_oen_o(ddr_dqs_n_oen), .ddr_dqs_n_ien_o(ddr_dqs_n_ien), .ddr_dqs_n_o(ddr_dqs_n_out), .ddr_dqs_n_i(ddr_dqs_n_in), + .ddr_dq_oen_o(ddr_dq_oen), .ddr_dq_o(ddr_dq_out), .ddr_dq_i(ddr_dq_in), + .ui_clk_i(ui_clk), + .dfi_clk_2x_i(dfi_clk_2x), .dfi_clk_1x_o(dfi_clk_1x), + .ui_clk_sync_rst_o(ui_clk_sync_rst), + .device_temp_o(device_temp) + ); +endmodule From caaa41d193b8930ee6739a75eb70079ac345ef38 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Wed, 28 Feb 2024 16:03:26 -0600 Subject: [PATCH 03/20] uncore: Add fifo --- src/uncore/fifo/fifo.sv | 43 ++++++++++++++++++++++++++++++++++ src/uncore/fifo/fifomem.sv | 24 +++++++++++++++++++ src/uncore/fifo/rptr_empty.sv | 37 +++++++++++++++++++++++++++++ src/uncore/fifo/sync_r2w.sv | 16 +++++++++++++ src/uncore/fifo/sync_w2r.sv | 16 +++++++++++++ src/uncore/fifo/wptr_full.sv | 44 +++++++++++++++++++++++++++++++++++ 6 files changed, 180 insertions(+) create mode 100644 src/uncore/fifo/fifo.sv create mode 100644 src/uncore/fifo/fifomem.sv create mode 100644 src/uncore/fifo/rptr_empty.sv create mode 100644 src/uncore/fifo/sync_r2w.sv create mode 100644 src/uncore/fifo/sync_w2r.sv create mode 100644 src/uncore/fifo/wptr_full.sv diff --git a/src/uncore/fifo/fifo.sv b/src/uncore/fifo/fifo.sv new file mode 100644 index 000000000..b6f3fcdc3 --- /dev/null +++ b/src/uncore/fifo/fifo.sv @@ -0,0 +1,43 @@ +module fifo #(parameter DSIZE = 8, + parameter ASIZE = 4) + (rdata, wfull, rempty, wdata, + winc, wclk, wrst_n, rinc, rclk, rrst_n); + + input logic [DSIZE-1:0] wdata; + input logic winc; + input logic wclk; + input logic wrst_n; + input logic rinc; + input logic rclk; + input logic rrst_n; + + output logic [DSIZE-1:0] rdata; + output logic wfull; + output logic rempty; + + logic [ASIZE-1:0] waddr, raddr; + logic [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr; + + sync_r2w sync_r2w (.wq2_rptr(wq2_rptr), .rptr(rptr), + .wclk(wclk), .wrst_n(wrst_n)); + sync_w2r sync_w2r (.rq2_wptr(rq2_wptr), .wptr(wptr), + .rclk(rclk), .rrst_n(rrst_n)); + + fifomem #(DSIZE, ASIZE) fifomem (.rdata(rdata), .wdata(wdata), + .waddr(waddr), .raddr(raddr), + .wclken(winc), .wfull(wfull), + .wclk(wclk)); + rptr_empty #(ASIZE) rptr_empty (.rempty(rempty), .raddr(raddr), + .rptr(rptr), .rq2_wptr(rq2_wptr), + .rinc(rinc), .rclk(rclk), + .rrst_n(rrst_n)); + wptr_full #(ASIZE) wptr_full (.wfull(wfull), .waddr(waddr), + .wptr(wptr), .wq2_rptr(wq2_rptr), + .winc(winc), .wclk(wclk), + .wrst_n(wrst_n)); + +endmodule // fifo1 + + + + diff --git a/src/uncore/fifo/fifomem.sv b/src/uncore/fifo/fifomem.sv new file mode 100644 index 000000000..3e3665c0d --- /dev/null +++ b/src/uncore/fifo/fifomem.sv @@ -0,0 +1,24 @@ + +// DATASIZE = Memory data word width +// ADDRSIZE = Number of mem address bits +module fifomem #(parameter DATASIZE = 8, + parameter ADDRSIZE = 4) + (rdata, wdata, waddr, raddr, wclken, wfull, wclk); + + input logic [DATASIZE-1:0] wdata; + input logic [ADDRSIZE-1:0] waddr; + input logic [ADDRSIZE-1:0] raddr; + input logic wclken; + input logic wfull; + input logic wclk; + output logic [DATASIZE-1:0] rdata; + + // RTL Verilog memory model + localparam DEPTH = 1 << ADDRSIZE; + logic [DATASIZE-1:0] mem [0:DEPTH-1]; + + assign rdata = mem[raddr]; + always @(posedge wclk) + if (wclken && !wfull) mem[waddr] <= wdata; + +endmodule // fifomem diff --git a/src/uncore/fifo/rptr_empty.sv b/src/uncore/fifo/rptr_empty.sv new file mode 100644 index 000000000..68ec5cb6e --- /dev/null +++ b/src/uncore/fifo/rptr_empty.sv @@ -0,0 +1,37 @@ +module rptr_empty #(parameter ADDRSIZE = 4) + (rempty, raddr, rptr, rq2_wptr, rinc, rclk, rrst_n); + + input logic [ADDRSIZE:0] rq2_wptr; + input logic rinc; + input logic rclk; + input logic rrst_n; + output logic rempty; + output logic [ADDRSIZE-1:0] raddr; + output logic [ADDRSIZE :0] rptr; + + logic [ADDRSIZE:0] rbin; + logic [ADDRSIZE:0] rgraynext; + logic [ADDRSIZE:0] rbinnext; + + //------------------- + // GRAYSTYLE2 pointer + //------------------- + always @(posedge rclk or negedge rrst_n) + if (!rrst_n) {rbin, rptr} <= 0; + else {rbin, rptr} <= {rbinnext, rgraynext}; + + // Memory read-address pointer (okay to use binary to address memory) + assign raddr = rbin[ADDRSIZE-1:0]; + assign rbinnext = rbin + (rinc & ~rempty); + assign rgraynext = (rbinnext>>1) ^ rbinnext; + + //--------------------------------------------------------------- + // FIFO empty when the next rptr == synchronized wptr or on reset + //--------------------------------------------------------------- + assign rempty_val = (rgraynext == rq2_wptr); + + always @(posedge rclk or negedge rrst_n) + if (!rrst_n) rempty <= 1'b1; + else rempty <= rempty_val; + +endmodule // rptr_empty diff --git a/src/uncore/fifo/sync_r2w.sv b/src/uncore/fifo/sync_r2w.sv new file mode 100644 index 000000000..97ac299a7 --- /dev/null +++ b/src/uncore/fifo/sync_r2w.sv @@ -0,0 +1,16 @@ +module sync_r2w #(parameter ADDRSIZE = 4) + (wq2_rptr, rptr, wclk, wrst_n); + + input logic [ADDRSIZE:0] rptr; + input logic wclk; + input logic wrst_n; + + output logic [ADDRSIZE:0] wq2_rptr; + + logic [ADDRSIZE:0] wq1_rptr; + + always @(posedge wclk or negedge wrst_n) + if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0; + else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr}; + +endmodule // sync_r2w diff --git a/src/uncore/fifo/sync_w2r.sv b/src/uncore/fifo/sync_w2r.sv new file mode 100644 index 000000000..f186968be --- /dev/null +++ b/src/uncore/fifo/sync_w2r.sv @@ -0,0 +1,16 @@ +module sync_w2r #(parameter ADDRSIZE = 4) + (rq2_wptr, wptr, rclk, rrst_n); + + input logic [ADDRSIZE:0] wptr; + input logic rclk; + input logic rrst_n; + + output logic [ADDRSIZE:0] rq2_wptr; + + logic [ADDRSIZE:0] rq1_wptr; + + always @(posedge rclk or negedge rrst_n) + if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0; + else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr}; + +endmodule // sync_w2r diff --git a/src/uncore/fifo/wptr_full.sv b/src/uncore/fifo/wptr_full.sv new file mode 100644 index 000000000..a6f4fdf9f --- /dev/null +++ b/src/uncore/fifo/wptr_full.sv @@ -0,0 +1,44 @@ +module wptr_full #(parameter ADDRSIZE = 4) + (wfull, waddr, wptr, wq2_rptr, winc, wclk, wrst_n); + + input logic [ADDRSIZE :0] wq2_rptr; + input logic winc; + input logic wclk; + input logic wrst_n; + + output logic wfull; + output logic [ADDRSIZE-1:0] waddr; + output logic [ADDRSIZE:0] wptr; + + logic [ADDRSIZE:0] wbin; + logic [ADDRSIZE:0] wgraynext; + logic [ADDRSIZE:0] wbinnext; + + // GRAYSTYLE2 pointer + always @(posedge wclk or negedge wrst_n) + if (!wrst_n) {wbin, wptr} <= 0; + else {wbin, wptr} <= {wbinnext, wgraynext}; + + // Memory write-address pointer (okay to use binary to address memory) + assign waddr = wbin[ADDRSIZE-1:0]; + assign wbinnext = wbin + (winc & ~wfull); + assign wgraynext = (wbinnext>>1) ^ wbinnext; + + //------------------------------------------------------------------ + // Simplified version of the three necessary full-tests: + // assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) && + // (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) && + // (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0])); + //------------------------------------------------------------------ + assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1], + wq2_rptr[ADDRSIZE-2:0]}); + + always @(posedge wclk or negedge wrst_n) + if (!wrst_n) + wfull <= 1'b0; + else + wfull <= wfull_val; + +endmodule // wptr_full + + From a868f2ff42763d3a8e38e2d601844fcdd18603a6 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 10:33:59 -0600 Subject: [PATCH 04/20] soc: Move SoC sv to a new folder --- .gitmodules | 2 +- {src/uncore => soc}/ahbxuiconverter.sv | 0 {src/uncore => soc}/basejump_stl | 0 {src/uncore => soc}/bsg_dmc_ahb.sv | 0 {src/uncore => soc}/fifo/fifo.sv | 0 {src/uncore => soc}/fifo/fifomem.sv | 0 {src/uncore => soc}/fifo/rptr_empty.sv | 0 {src/uncore => soc}/fifo/sync_r2w.sv | 0 {src/uncore => soc}/fifo/sync_w2r.sv | 0 {src/uncore => soc}/fifo/wptr_full.sv | 0 10 files changed, 1 insertion(+), 1 deletion(-) rename {src/uncore => soc}/ahbxuiconverter.sv (100%) rename {src/uncore => soc}/basejump_stl (100%) rename {src/uncore => soc}/bsg_dmc_ahb.sv (100%) rename {src/uncore => soc}/fifo/fifo.sv (100%) rename {src/uncore => soc}/fifo/fifomem.sv (100%) rename {src/uncore => soc}/fifo/rptr_empty.sv (100%) rename {src/uncore => soc}/fifo/sync_r2w.sv (100%) rename {src/uncore => soc}/fifo/sync_w2r.sv (100%) rename {src/uncore => soc}/fifo/wptr_full.sv (100%) diff --git a/.gitmodules b/.gitmodules index 4be9799dc..da4ce37c1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,5 +30,5 @@ path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git [submodule "src/uncore/basejump_stl"] - path = src/uncore/basejump_stl + path = soc/basejump_stl url = https://github.com/bespoke-silicon-group/basejump_stl diff --git a/src/uncore/ahbxuiconverter.sv b/soc/ahbxuiconverter.sv similarity index 100% rename from src/uncore/ahbxuiconverter.sv rename to soc/ahbxuiconverter.sv diff --git a/src/uncore/basejump_stl b/soc/basejump_stl similarity index 100% rename from src/uncore/basejump_stl rename to soc/basejump_stl diff --git a/src/uncore/bsg_dmc_ahb.sv b/soc/bsg_dmc_ahb.sv similarity index 100% rename from src/uncore/bsg_dmc_ahb.sv rename to soc/bsg_dmc_ahb.sv diff --git a/src/uncore/fifo/fifo.sv b/soc/fifo/fifo.sv similarity index 100% rename from src/uncore/fifo/fifo.sv rename to soc/fifo/fifo.sv diff --git a/src/uncore/fifo/fifomem.sv b/soc/fifo/fifomem.sv similarity index 100% rename from src/uncore/fifo/fifomem.sv rename to soc/fifo/fifomem.sv diff --git a/src/uncore/fifo/rptr_empty.sv b/soc/fifo/rptr_empty.sv similarity index 100% rename from src/uncore/fifo/rptr_empty.sv rename to soc/fifo/rptr_empty.sv diff --git a/src/uncore/fifo/sync_r2w.sv b/soc/fifo/sync_r2w.sv similarity index 100% rename from src/uncore/fifo/sync_r2w.sv rename to soc/fifo/sync_r2w.sv diff --git a/src/uncore/fifo/sync_w2r.sv b/soc/fifo/sync_w2r.sv similarity index 100% rename from src/uncore/fifo/sync_w2r.sv rename to soc/fifo/sync_w2r.sv diff --git a/src/uncore/fifo/wptr_full.sv b/soc/fifo/wptr_full.sv similarity index 100% rename from src/uncore/fifo/wptr_full.sv rename to soc/fifo/wptr_full.sv From c2ff55af111783ddc6cc116cbefa75595b5ee512 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 10:35:39 -0600 Subject: [PATCH 05/20] uncore: Revert changes to uncore.sv Previously I made changes to uncore.sv to enable external RAM with the bsg_dmc memory controller. As it turns out, these changes were unnecessary as I should have implemented the bsg_dmc interface at the toplevel external AHB bus. --- src/uncore/uncore.sv | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 48e87fe2b..22e0a35fc 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -63,17 +63,15 @@ module uncore import cvw::*; #(parameter cvw_t P)( logic [P.XLEN-1:0] HREADRam, HREADSDC; - logic [12:0] HSELRegions; + logic [11:0] HSELRegions; logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSPI; logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID; logic HRESPRam, HRESPSDC; logic HREADYRam, HRESPSDCD; - logic [P.XLEN-1:0] HREADBootRom; + logic [P.XLEN-1:0] HREADBootRom; logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC; - logic [P.XLEN-1:0] HREADBsgDmc; - logic HSELBsgDmc, HSELBsgDmcD, HRESPBsgDmc, HREADYBsgDmc; logic HSELNoneD; - logic UARTIntr, GPIOIntr, SPIIntr; + logic UARTIntr,GPIOIntr, SPIIntr; logic SDCIntM; logic PCLK, PRESETn, PWRITE, PENABLE; @@ -94,7 +92,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELBsgDmc, HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[12:1]; + assign {HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1]; // AHB -> APB bridge ahbapbbridge #(P, 5) ahbapbbridge ( @@ -160,38 +158,30 @@ module uncore import cvw::*; #(parameter cvw_t P)( assign SPIOut = 0; assign SPICS = 0; assign SPIIntr = 0; end - // FIXME: Do we need to block this off in an if (like SPI above)? - bsg_dmc_ahb #(P.PA_BITS, P.XLEN) external_ram ( - .HCLK, .HRESETn, .HSEL(HSELBsgDmc), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, - .HRDATA(HREADBsgDmc), .HRESP(HRESPBsgDmc), .HREADYOUT(HREADYBsgDmc)); - // AHB Read Multiplexer assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) | - ({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) | + ({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) | ({P.XLEN{HSELBRIDGED}} & HREADBRIDGE) | - ({P.XLEN{HSELBootRomD}} & HREADBootRom) | - ({P.XLEN{HSELBsgDmcD}} & HREADBsgDmc); + ({P.XLEN{HSELBootRomD}} & HREADBootRom); assign HRESP = HSELRamD & HRESPRam | (HSELEXTD | HSELEXTSDCD) & HRESPEXT | HSELBRIDGE & HRESPBRIDGE | - HSELBootRomD & HRESPBootRom | - HSELBsgDmcD & HRESPBsgDmc; + HSELBootRomD & HRESPBootRom; assign HREADY = HSELRamD & HREADYRam | - (HSELEXTD | HSELEXTSDCD) & HREADYEXT | + (HSELEXTD | HSELEXTSDCD) & HREADYEXT | HSELBRIDGED & HREADYBRIDGE | HSELBootRomD & HREADYBootRom | - HSELBsgDmcD & HREADYBsgDmc | HSELNoneD; // don't lock up the bus if no region is being accessed // Address Decoder Delay (figure 4-2 in spec) // The select for HREADY needs to be based on the address phase address. If the device // takes more than 1 cycle to repsond it needs to hold on to the old select until the - // device is ready. Hence this register must be selectively enabled by HREADY. - // However on reset None must be selected. - flopenl #(13) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 13'b1, - {HSELBsgDmcD, HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, - HSELCLINTD, HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD}); + // device is ready. Hense this register must be selectively enabled by HREADY. + // However on reset None must be seleted. + flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1, + {HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD, + HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD}); flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED); endmodule From 1ea8f99625ca9d8dd5553a1d2839b8fbbf778ad0 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 11:13:56 -0600 Subject: [PATCH 06/20] soc/fifo: Add copyright headers --- soc/fifo/fifo.sv | 29 +++++++++++++++++++++++++++++ soc/fifo/fifomem.sv | 28 +++++++++++++++++++++++++++- soc/fifo/rptr_empty.sv | 28 ++++++++++++++++++++++++++++ soc/fifo/sync_r2w.sv | 28 ++++++++++++++++++++++++++++ soc/fifo/sync_w2r.sv | 28 ++++++++++++++++++++++++++++ soc/fifo/wptr_full.sv | 28 ++++++++++++++++++++++++++++ 6 files changed, 168 insertions(+), 1 deletion(-) diff --git a/soc/fifo/fifo.sv b/soc/fifo/fifo.sv index b6f3fcdc3..a5102a471 100644 --- a/soc/fifo/fifo.sv +++ b/soc/fifo/fifo.sv @@ -1,3 +1,32 @@ +/////////////////////////////////////////// +// fifo.sv +// +// Written: Clifford E Cummings 16 June 2005 +// Modified: james.stine@okstate.edu 19 February 2024 +// +// Purpose: Asynchronous FIFO +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// + module fifo #(parameter DSIZE = 8, parameter ASIZE = 4) (rdata, wfull, rempty, wdata, diff --git a/soc/fifo/fifomem.sv b/soc/fifo/fifomem.sv index 3e3665c0d..1c7fdc045 100644 --- a/soc/fifo/fifomem.sv +++ b/soc/fifo/fifomem.sv @@ -1,5 +1,31 @@ +/////////////////////////////////////////// +// fifomem.sv +// +// Written: Clifford E. Cummings 16 June 2005 +// Modified: james.stine@okstate.edu 19 February 2024 +// +// Purpose: FIFO memory buffer +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// -// DATASIZE = Memory data word width +// DATASIZE = Memory data word width // ADDRSIZE = Number of mem address bits module fifomem #(parameter DATASIZE = 8, parameter ADDRSIZE = 4) diff --git a/soc/fifo/rptr_empty.sv b/soc/fifo/rptr_empty.sv index 68ec5cb6e..79bb0fc08 100644 --- a/soc/fifo/rptr_empty.sv +++ b/soc/fifo/rptr_empty.sv @@ -1,3 +1,31 @@ +/////////////////////////////////////////// +// rptr_empty.sv +// +// Written: Clifford E Cummings 16 June 2005 +// Modified: james.stine@okstate.edu 19 February 2024 +// +// Purpose: FIFO read pointer and empty generation logic +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// module rptr_empty #(parameter ADDRSIZE = 4) (rempty, raddr, rptr, rq2_wptr, rinc, rclk, rrst_n); diff --git a/soc/fifo/sync_r2w.sv b/soc/fifo/sync_r2w.sv index 97ac299a7..935d04f5a 100644 --- a/soc/fifo/sync_r2w.sv +++ b/soc/fifo/sync_r2w.sv @@ -1,3 +1,31 @@ +/////////////////////////////////////////// +// sync_r2w.sv +// +// Written: Clifford E Cummings 16 June 2005 +// Modified: james.stine@okstate.edu 19 February 2024 +// +// Purpose: FIFO read-domain to write-domain synchronizer +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// module sync_r2w #(parameter ADDRSIZE = 4) (wq2_rptr, rptr, wclk, wrst_n); diff --git a/soc/fifo/sync_w2r.sv b/soc/fifo/sync_w2r.sv index f186968be..6a666bfc6 100644 --- a/soc/fifo/sync_w2r.sv +++ b/soc/fifo/sync_w2r.sv @@ -1,3 +1,31 @@ +/////////////////////////////////////////// +// sync_w2r.sv +// +// Written: Clifford E Cummings 16 June 2005 +// Modified: james.stine@okstate.edu 19 February 2024 +// +// Purpose: FIFO write-domain to read-domain synchronizer +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// module sync_w2r #(parameter ADDRSIZE = 4) (rq2_wptr, wptr, rclk, rrst_n); diff --git a/soc/fifo/wptr_full.sv b/soc/fifo/wptr_full.sv index a6f4fdf9f..19ff6517e 100644 --- a/soc/fifo/wptr_full.sv +++ b/soc/fifo/wptr_full.sv @@ -1,3 +1,31 @@ +/////////////////////////////////////////// +// wptr_full.sv +// +// Written: Clifford E Cummings 16 June 2005 +// Modified: james.stine@okstate.edu 19 February 2024 +// +// Purpose: FIFO write pointer and full generation logic +// +// Documentation: +// +// 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. +//////////////////////////////////////////////////////////////////////////////////////////////// module wptr_full #(parameter ADDRSIZE = 4) (wfull, waddr, wptr, wq2_rptr, winc, wclk, wrst_n); From 553a8524e2150d5ed7d3daf13b0ccea33a8d796c Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 11:22:40 -0600 Subject: [PATCH 07/20] soc: organize SoC sources --- .gitmodules | 2 +- soc/README.md | 1 + soc/{ => src}/ahbxuiconverter.sv | 2 +- soc/{ => src}/basejump_stl | 0 soc/{ => src}/bsg_dmc_ahb.sv | 2 +- soc/{ => src}/fifo/fifo.sv | 0 soc/{ => src}/fifo/fifomem.sv | 0 soc/{ => src}/fifo/rptr_empty.sv | 0 soc/{ => src}/fifo/sync_r2w.sv | 0 soc/{ => src}/fifo/sync_w2r.sv | 0 soc/{ => src}/fifo/wptr_full.sv | 0 11 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 soc/README.md rename soc/{ => src}/ahbxuiconverter.sv (98%) rename soc/{ => src}/basejump_stl (100%) rename soc/{ => src}/bsg_dmc_ahb.sv (99%) rename soc/{ => src}/fifo/fifo.sv (100%) rename soc/{ => src}/fifo/fifomem.sv (100%) rename soc/{ => src}/fifo/rptr_empty.sv (100%) rename soc/{ => src}/fifo/sync_r2w.sv (100%) rename soc/{ => src}/fifo/sync_w2r.sv (100%) rename soc/{ => src}/fifo/wptr_full.sv (100%) diff --git a/.gitmodules b/.gitmodules index da4ce37c1..844387a0f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,5 +30,5 @@ path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git [submodule "src/uncore/basejump_stl"] - path = soc/basejump_stl + path = soc/src/basejump_stl url = https://github.com/bespoke-silicon-group/basejump_stl diff --git a/soc/README.md b/soc/README.md new file mode 100644 index 000000000..0868cb748 --- /dev/null +++ b/soc/README.md @@ -0,0 +1 @@ +This folder contains resources related to the Wally SoC effort. diff --git a/soc/ahbxuiconverter.sv b/soc/src/ahbxuiconverter.sv similarity index 98% rename from soc/ahbxuiconverter.sv rename to soc/src/ahbxuiconverter.sv index cb607889b..2d672a796 100644 --- a/soc/ahbxuiconverter.sv +++ b/soc/src/ahbxuiconverter.sv @@ -1,7 +1,7 @@ /////////////////////////////////////////// // ahbxuiconverter.sv // -// Written: infinitymdm@gmail.com +// Written: infinitymdm@gmail.com 29 February 2024 // // Purpose: AHB to Xilinx UI converter // diff --git a/soc/basejump_stl b/soc/src/basejump_stl similarity index 100% rename from soc/basejump_stl rename to soc/src/basejump_stl diff --git a/soc/bsg_dmc_ahb.sv b/soc/src/bsg_dmc_ahb.sv similarity index 99% rename from soc/bsg_dmc_ahb.sv rename to soc/src/bsg_dmc_ahb.sv index 83de36b86..875e7b99c 100644 --- a/soc/bsg_dmc_ahb.sv +++ b/soc/src/bsg_dmc_ahb.sv @@ -1,7 +1,7 @@ /////////////////////////////////////////// // bsg_dmc_ahb.sv // -// Written: infinitymdm@gmail.com +// Written: infinitymdm@gmail.com 29 February 2024 // // Purpose: BSG controller and LPDDRDRAM presenting an AHB interface // diff --git a/soc/fifo/fifo.sv b/soc/src/fifo/fifo.sv similarity index 100% rename from soc/fifo/fifo.sv rename to soc/src/fifo/fifo.sv diff --git a/soc/fifo/fifomem.sv b/soc/src/fifo/fifomem.sv similarity index 100% rename from soc/fifo/fifomem.sv rename to soc/src/fifo/fifomem.sv diff --git a/soc/fifo/rptr_empty.sv b/soc/src/fifo/rptr_empty.sv similarity index 100% rename from soc/fifo/rptr_empty.sv rename to soc/src/fifo/rptr_empty.sv diff --git a/soc/fifo/sync_r2w.sv b/soc/src/fifo/sync_r2w.sv similarity index 100% rename from soc/fifo/sync_r2w.sv rename to soc/src/fifo/sync_r2w.sv diff --git a/soc/fifo/sync_w2r.sv b/soc/src/fifo/sync_w2r.sv similarity index 100% rename from soc/fifo/sync_w2r.sv rename to soc/src/fifo/sync_w2r.sv diff --git a/soc/fifo/wptr_full.sv b/soc/src/fifo/wptr_full.sv similarity index 100% rename from soc/fifo/wptr_full.sv rename to soc/src/fifo/wptr_full.sv From 6098d3f1a7b8fd55be962895815d275f5e5e45df Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 12:27:06 -0600 Subject: [PATCH 08/20] soc/src/bsg_dmc_ahb.sv: Fix syntax errors --- soc/src/bsg_dmc_ahb.sv | 46 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/soc/src/bsg_dmc_ahb.sv b/soc/src/bsg_dmc_ahb.sv index 875e7b99c..6de00be03 100644 --- a/soc/src/bsg_dmc_ahb.sv +++ b/soc/src/bsg_dmc_ahb.sv @@ -91,33 +91,33 @@ module bsg_dmc_ahb // Use a /6 clock divider until PLL is integrated. TODO: Replace logic ui_clk; - integer clk_counter = 0; + integer clk_counter; always @(posedge HCLK) begin - counter <= counter + 1; - if (counter >= 6) counter <= 0; - ui_clk <= (counter >= 3); + clk_counter <= clk_counter + 1; + if (clk_counter >= 6) clk_counter <= 0; + ui_clk <= (clk_counter >= 3); end // TODO: Figure out how to initialize dmc_config correctly always_comb begin: bsg_dmc_config - dmc_p.trefi = 1023; - dmc_p.tmrd = 1; - dmc_p.trfc = 15; - dmc_p.trc = 10; - dmc_p.trp = 2; - dmc_p.tras = 7; - dmc_p.trrd = 1; - dmc_p.trcd = 2; - dmc_p.twr = 10; - dmc_p.twtr = 7; - dmc_p.trtp = 10; - dmc_p.tcas = 3; - dmc_p.col_width = 11; - dmc_p.row_width = 14; - dmc_p.bank_width = 2; - dmc_p.dqs_sel_cal = 3; - dmc_p.init_cycles = 40010; - dmc_p.bank_pos = 25; + dmc_config.trefi = 1023; + dmc_config.tmrd = 1; + dmc_config.trfc = 15; + dmc_config.trc = 10; + dmc_config.trp = 2; + dmc_config.tras = 7; + dmc_config.trrd = 1; + dmc_config.trcd = 2; + dmc_config.twr = 10; + dmc_config.twtr = 7; + dmc_config.trtp = 10; + dmc_config.tcas = 3; + dmc_config.col_width = 11; + dmc_config.row_width = 14; + dmc_config.bank_width = 2; + dmc_config.dqs_sel_cal = 3; + dmc_config.init_cycles = 40010; + dmc_config.bank_pos = 25; end ahbxuiconverter #(ADDR_SIZE, DATA_SIZE) bsg_dmc_ahb_ui_converter ( @@ -134,7 +134,7 @@ module bsg_dmc_ahb .ui_addr_width_p(ADDR_SIZE), .ui_data_width_p(DATA_SIZE), .burst_data_width_p(BURST_DATA_SIZE), - .dq_data_width_p(DQ_DATA_SIZE), + .dq_data_width_p(DATA_SIZE/2), .cmd_afifo_depth(FIFO_DEPTH), .cmd_sfifo_depth(FIFO_DEPTH) ) dmc ( From c3727a3ee6f9dff1238b8c3e7ec6e2c623708a4b Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 15:38:57 -0600 Subject: [PATCH 09/20] soc/src/bsg_dmc_ahb.sv: Fix incorrect parameters --- soc/src/bsg_dmc_ahb.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soc/src/bsg_dmc_ahb.sv b/soc/src/bsg_dmc_ahb.sv index 6de00be03..7a1cc0455 100644 --- a/soc/src/bsg_dmc_ahb.sv +++ b/soc/src/bsg_dmc_ahb.sv @@ -135,8 +135,8 @@ module bsg_dmc_ahb .ui_data_width_p(DATA_SIZE), .burst_data_width_p(BURST_DATA_SIZE), .dq_data_width_p(DATA_SIZE/2), - .cmd_afifo_depth(FIFO_DEPTH), - .cmd_sfifo_depth(FIFO_DEPTH) + .cmd_afifo_depth_p(FIFO_DEPTH), + .cmd_sfifo_depth_p(FIFO_DEPTH) ) dmc ( .async_reset_tag_i(dmc_rst_tag), .bsg_dly_tag_i(dmc_dly_tag), .bsg_dly_trigger_tag_i(dmc_dly_trigger_tag), .bsg_ds_tag_i(dmc_ds_tag), From fc800180c7d5b45979b09284956db15ed504af9b Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Thu, 29 Feb 2024 16:08:46 -0600 Subject: [PATCH 10/20] soc/src/fifo/fifo.sv: Fix missing parameter --- soc/src/fifo/fifo.sv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soc/src/fifo/fifo.sv b/soc/src/fifo/fifo.sv index a5102a471..1e6d91a55 100644 --- a/soc/src/fifo/fifo.sv +++ b/soc/src/fifo/fifo.sv @@ -2,7 +2,7 @@ // fifo.sv // // Written: Clifford E Cummings 16 June 2005 -// Modified: james.stine@okstate.edu 19 February 2024 +// Modified: infinitymdm@gmail.com 29 February 2024 // // Purpose: Asynchronous FIFO // @@ -47,9 +47,9 @@ module fifo #(parameter DSIZE = 8, logic [ASIZE-1:0] waddr, raddr; logic [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr; - sync_r2w sync_r2w (.wq2_rptr(wq2_rptr), .rptr(rptr), + sync_r2w #(ASIZE) sync_r2w (.wq2_rptr(wq2_rptr), .rptr(rptr), .wclk(wclk), .wrst_n(wrst_n)); - sync_w2r sync_w2r (.rq2_wptr(rq2_wptr), .wptr(wptr), + sync_w2r #(ASIZE) sync_w2r (.rq2_wptr(rq2_wptr), .wptr(wptr), .rclk(rclk), .rrst_n(rrst_n)); fifomem #(DSIZE, ASIZE) fifomem (.rdata(rdata), .wdata(wdata), From 7c7c122dd2e2aec07691875e2e0e20af27baa513 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Fri, 1 Mar 2024 10:43:33 -0600 Subject: [PATCH 11/20] soc: Fix basejump_stl submodule path --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 844387a0f..ab5737479 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,6 +29,6 @@ [submodule "addins/ahbsdc"] path = addins/ahbsdc url = http://github.com/JacobPease/ahbsdc.git -[submodule "src/uncore/basejump_stl"] +[submodule "soc/src/basejump_stl"] path = soc/src/basejump_stl url = https://github.com/bespoke-silicon-group/basejump_stl From ab8aa5f7cf31d3bb45e466b8a997dda3b07d3bd0 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Fri, 1 Mar 2024 12:17:54 -0600 Subject: [PATCH 12/20] soc: Add shallow=true to basejump_stl submodule --- .gitmodules | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitmodules b/.gitmodules index ab5737479..3961a407c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -32,3 +32,4 @@ [submodule "soc/src/basejump_stl"] path = soc/src/basejump_stl url = https://github.com/bespoke-silicon-group/basejump_stl + shallow = true From 4d02775efe14a6a1102e9b5c78810f0e1e8b21a2 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Mon, 4 Mar 2024 10:40:51 -0600 Subject: [PATCH 13/20] soc/src: Update basejump_stl to current master --- soc/src/basejump_stl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/src/basejump_stl b/soc/src/basejump_stl index 14f29e4d8..2a7310619 160000 --- a/soc/src/basejump_stl +++ b/soc/src/basejump_stl @@ -1 +1 @@ -Subproject commit 14f29e4d8a498ad62ec05fe232407f9d887e36a9 +Subproject commit 2a7310619aaf47362be74fcd34125a99b82cd388 From 84e05066b179db89be7b42fd1e3844eee9c5404d Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Wed, 6 Mar 2024 16:12:03 -0600 Subject: [PATCH 14/20] soc/src: Fix small FIFO bugs, correct DDR paramaterization --- soc/src/bsg_dmc_ahb.sv | 96 +++++++++++++++++++------------------- soc/src/fifo/rptr_empty.sv | 67 +++++++++++++------------- soc/src/fifo/wptr_full.sv | 72 ++++++++++++++-------------- 3 files changed, 117 insertions(+), 118 deletions(-) diff --git a/soc/src/bsg_dmc_ahb.sv b/soc/src/bsg_dmc_ahb.sv index 7a1cc0455..25045823f 100644 --- a/soc/src/bsg_dmc_ahb.sv +++ b/soc/src/bsg_dmc_ahb.sv @@ -32,41 +32,39 @@ module bsg_dmc_ahb import bsg_tag_pkg::*; import bsg_dmc_pkg::*; #( - parameter ADDR_SIZE = 28, - parameter DATA_SIZE = 64, - parameter BURST_LENGTH = 8, - parameter FIFO_DEPTH = 4, + parameter AHB_ADDR_SIZE = 28, + parameter AHB_DATA_SIZE = 64, + parameter DDR_DATA_SIZE = 32, + parameter BURST_LENGTH = 8, + parameter FIFO_DEPTH = 4 ) ( - input logic HCLK, HRESETn, - input logic HSEL, - input logic [ADDR_SIZE-1:0] HADDR, - input logic [DATA_SIZE-1:0] HWDATA, - input logic [DATA_SIZE/8-1:0] HWSTRB, - input logic HWRITE, - input logic [1:0] HTRANS, - input logic HREADY, - output logic [DATA_SIZE-1:0] HRDATA, - output logic HRESP, HREADYOUT, - //input logic ui_clk // Add this once PLL is integrated - output logic ddr_ck_p, ddr_ck_n, ddr_cke, - output logic [2:0] ddr_ba, - output logic [15:0] ddr_addr, - output logic ddr_cs, ddr_ras, ddr_cas, - output logic ddr_we, ddr_reset, ddr_odt, - output logic [DATA_SIZE/16-1:0] ddr_dm_oen, ddr_dm, - output logic [DATA_SIZE/16-1:0] ddr_dqs_p_oen, ddr_dqs_p_ien, ddr_dqs_p_out, - input logic [DATA_SIZE/16-1:0] ddr_dqs_p_in, - output logic [DATA_SIZE/16-1:0] ddr_dqs_n_oen, ddr_dqs_n_ien, ddr_dqs_n_out, - input logic [DATA_SIZE/16-1:0] ddr_dqs_n_in, - output logic [DATA_SIZE/2-1:0] ddr_dq_oen, ddr_dq_out, - input logic [DATA_SIZE/2-1:0] ddr_dq_in, - input logic dfi_clk_2x, - output logic dfi_clk_1x + input logic HCLK, HRESETn, + input logic HSEL, + input logic [AHB_ADDR_SIZE-1:0] HADDR, + input logic [AHB_DATA_SIZE-1:0] HWDATA, + input logic [AHB_DATA_SIZE/8-1:0] HWSTRB, + input logic HWRITE, + input logic [1:0] HTRANS, + input logic HREADY, + output logic [AHB_DATA_SIZE-1:0] HRDATA, + output logic HRESP, HREADYOUT, + //input logic ui_clk, // Add this once PLL is integrated + output logic ddr_ck_p, ddr_ck_n, ddr_cke, + output logic [2:0] ddr_ba, + output logic [13:0] ddr_addr, + output logic ddr_cs, ddr_ras, ddr_cas, + output logic ddr_we, ddr_reset, ddr_odt, + output logic [DDR_DATA_SIZE/8-1:0] ddr_dm_oen, ddr_dm, + output logic [DDR_DATA_SIZE/8-1:0] ddr_dqs_p_oen, ddr_dqs_p_ien, ddr_dqs_p_out, + input logic [DDR_DATA_SIZE/8-1:0] ddr_dqs_p_in, + output logic [DDR_DATA_SIZE/8-1:0] ddr_dqs_n_oen, ddr_dqs_n_ien, ddr_dqs_n_out, + input logic [DDR_DATA_SIZE/8-1:0] ddr_dqs_n_in, + output logic [DDR_DATA_SIZE-1:0] ddr_dq_oen, ddr_dq_out, + input logic [DDR_DATA_SIZE-1:0] ddr_dq_in, + input logic dfi_clk_2x, + output logic dfi_clk_1x ); - localparam BURST_DATA_SIZE = DATA_SIZE * BURST_LENGTH; - // localparam DQ_DATA_SIZE = DATA_SIZE >> 1; - // Global async reset logic sys_reset; @@ -76,18 +74,18 @@ module bsg_dmc_ahb bsg_dmc_s dmc_config; // UI signals - logic ui_clk_sync_rst; - logic [ADDR_SIZE-1:0] app_addr; - logic [2:0] app_cmd; - logic app_en, app_rdy, app_wdf_wren; - logic [DATA_SIZE-1:0] app_wdf_data; - logic [DATA_SIZE/8-1:0] app_wdf_mask; - logic app_wdf_end, app_wdf_rdy; - logic [DATA_SIZE-1:0] app_rd_data; - logic app_rd_data_end, app_rd_data_valid; - logic app_ref_ack, app_zq_ack, app_sr_active; // Sink unused UI signals - logic init_calib_complete; - logic [11:0] device_temp; // Reserved + logic ui_clk_sync_rst; + logic [AHB_ADDR_SIZE-1:0] app_addr; + logic [2:0] app_cmd; + logic app_en, app_rdy, app_wdf_wren; + logic [AHB_DATA_SIZE-1:0] app_wdf_data; + logic [AHB_DATA_SIZE/8-1:0] app_wdf_mask; + logic app_wdf_end, app_wdf_rdy; + logic [AHB_DATA_SIZE-1:0] app_rd_data; + logic app_rd_data_end, app_rd_data_valid; + logic app_ref_ack, app_zq_ack, app_sr_active; // Sink unused UI signals + logic init_calib_complete; + logic [11:0] device_temp; // Reserved // Use a /6 clock divider until PLL is integrated. TODO: Replace logic ui_clk; @@ -120,7 +118,7 @@ module bsg_dmc_ahb dmc_config.bank_pos = 25; end - ahbxuiconverter #(ADDR_SIZE, DATA_SIZE) bsg_dmc_ahb_ui_converter ( + ahbxuiconverter #(AHB_ADDR_SIZE, AHB_DATA_SIZE) bsg_dmc_ahb_ui_converter ( .HCLK, .HRESETn, .HSEL, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA, .HRESP, .HREADYOUT, .sys_reset, .ui_clk, .ui_clk_sync_rst, .app_addr, .app_cmd, .app_en, .app_rdy, @@ -131,10 +129,10 @@ module bsg_dmc_ahb bsg_dmc #( .num_adgs_p(1), - .ui_addr_width_p(ADDR_SIZE), - .ui_data_width_p(DATA_SIZE), - .burst_data_width_p(BURST_DATA_SIZE), - .dq_data_width_p(DATA_SIZE/2), + .ui_addr_width_p(AHB_ADDR_SIZE), + .ui_data_width_p(AHB_DATA_SIZE), + .burst_data_width_p(AHB_DATA_SIZE * BURST_LENGTH), + .dq_data_width_p(DDR_DATA_SIZE), .cmd_afifo_depth_p(FIFO_DEPTH), .cmd_sfifo_depth_p(FIFO_DEPTH) ) dmc ( diff --git a/soc/src/fifo/rptr_empty.sv b/soc/src/fifo/rptr_empty.sv index 79bb0fc08..5bc7d5e37 100644 --- a/soc/src/fifo/rptr_empty.sv +++ b/soc/src/fifo/rptr_empty.sv @@ -2,7 +2,7 @@ // rptr_empty.sv // // Written: Clifford E Cummings 16 June 2005 -// Modified: james.stine@okstate.edu 19 February 2024 +// Modified: infinitymdm@gmail.com 5 March 2024 // // Purpose: FIFO read pointer and empty generation logic // @@ -27,39 +27,40 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// module rptr_empty #(parameter ADDRSIZE = 4) - (rempty, raddr, rptr, rq2_wptr, rinc, rclk, rrst_n); + (rempty, raddr, rptr, rq2_wptr, rinc, rclk, rrst_n); - input logic [ADDRSIZE:0] rq2_wptr; - input logic rinc; - input logic rclk; - input logic rrst_n; - output logic rempty; - output logic [ADDRSIZE-1:0] raddr; - output logic [ADDRSIZE :0] rptr; + input logic [ADDRSIZE:0] rq2_wptr; + input logic rinc; + input logic rclk; + input logic rrst_n; + output logic rempty; + output logic [ADDRSIZE-1:0] raddr; + output logic [ADDRSIZE :0] rptr; - logic [ADDRSIZE:0] rbin; - logic [ADDRSIZE:0] rgraynext; - logic [ADDRSIZE:0] rbinnext; + logic rempty_val; + logic [ADDRSIZE:0] rbin; + logic [ADDRSIZE:0] rgraynext; + logic [ADDRSIZE:0] rbinnext; + + //------------------- + // GRAYSTYLE2 pointer + //------------------- + always @(posedge rclk or negedge rrst_n) + if (!rrst_n) {rbin, rptr} <= 0; + else {rbin, rptr} <= {rbinnext, rgraynext}; + + // Memory read-address pointer (okay to use binary to address memory) + assign raddr = rbin[ADDRSIZE-1:0]; + assign rbinnext = rbin + (rinc & ~rempty); + assign rgraynext = (rbinnext>>1) ^ rbinnext; + + //--------------------------------------------------------------- + // FIFO empty when the next rptr == synchronized wptr or on reset + //--------------------------------------------------------------- + assign rempty_val = (rgraynext == rq2_wptr); + + always @(posedge rclk or negedge rrst_n) + if (!rrst_n) rempty <= 1'b1; + else rempty <= rempty_val; - //------------------- - // GRAYSTYLE2 pointer - //------------------- - always @(posedge rclk or negedge rrst_n) - if (!rrst_n) {rbin, rptr} <= 0; - else {rbin, rptr} <= {rbinnext, rgraynext}; - - // Memory read-address pointer (okay to use binary to address memory) - assign raddr = rbin[ADDRSIZE-1:0]; - assign rbinnext = rbin + (rinc & ~rempty); - assign rgraynext = (rbinnext>>1) ^ rbinnext; - - //--------------------------------------------------------------- - // FIFO empty when the next rptr == synchronized wptr or on reset - //--------------------------------------------------------------- - assign rempty_val = (rgraynext == rq2_wptr); - - always @(posedge rclk or negedge rrst_n) - if (!rrst_n) rempty <= 1'b1; - else rempty <= rempty_val; - endmodule // rptr_empty diff --git a/soc/src/fifo/wptr_full.sv b/soc/src/fifo/wptr_full.sv index 19ff6517e..40fb83654 100644 --- a/soc/src/fifo/wptr_full.sv +++ b/soc/src/fifo/wptr_full.sv @@ -2,7 +2,7 @@ // wptr_full.sv // // Written: Clifford E Cummings 16 June 2005 -// Modified: james.stine@okstate.edu 19 February 2024 +// Modified: infinitymdm@gmail.com 5 March 2024 // // Purpose: FIFO write pointer and full generation logic // @@ -27,45 +27,45 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// module wptr_full #(parameter ADDRSIZE = 4) - (wfull, waddr, wptr, wq2_rptr, winc, wclk, wrst_n); + (wfull, waddr, wptr, wq2_rptr, winc, wclk, wrst_n); - input logic [ADDRSIZE :0] wq2_rptr; - input logic winc; - input logic wclk; - input logic wrst_n; - - output logic wfull; - output logic [ADDRSIZE-1:0] waddr; - output logic [ADDRSIZE:0] wptr; - - logic [ADDRSIZE:0] wbin; - logic [ADDRSIZE:0] wgraynext; - logic [ADDRSIZE:0] wbinnext; + input logic [ADDRSIZE:0] wq2_rptr; + input logic winc; + input logic wclk; + input logic wrst_n; + output logic wfull; + output logic [ADDRSIZE-1:0] waddr; + output logic [ADDRSIZE:0] wptr; - // GRAYSTYLE2 pointer - always @(posedge wclk or negedge wrst_n) - if (!wrst_n) {wbin, wptr} <= 0; - else {wbin, wptr} <= {wbinnext, wgraynext}; + logic wfull_val; + logic [ADDRSIZE:0] wbin; + logic [ADDRSIZE:0] wgraynext; + logic [ADDRSIZE:0] wbinnext; - // Memory write-address pointer (okay to use binary to address memory) - assign waddr = wbin[ADDRSIZE-1:0]; - assign wbinnext = wbin + (winc & ~wfull); - assign wgraynext = (wbinnext>>1) ^ wbinnext; + // GRAYSTYLE2 pointer + always @(posedge wclk or negedge wrst_n) + if (!wrst_n) {wbin, wptr} <= 0; + else {wbin, wptr} <= {wbinnext, wgraynext}; - //------------------------------------------------------------------ - // Simplified version of the three necessary full-tests: - // assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) && - // (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) && - // (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0])); - //------------------------------------------------------------------ - assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1], - wq2_rptr[ADDRSIZE-2:0]}); - - always @(posedge wclk or negedge wrst_n) - if (!wrst_n) - wfull <= 1'b0; - else - wfull <= wfull_val; + // Memory write-address pointer (okay to use binary to address memory) + assign waddr = wbin[ADDRSIZE-1:0]; + assign wbinnext = wbin + (winc & ~wfull); + assign wgraynext = (wbinnext>>1) ^ wbinnext; + + //------------------------------------------------------------------ + // Simplified version of the three necessary full-tests: + // assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) && + // (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) && + // (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0])); + //------------------------------------------------------------------ + assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1], + wq2_rptr[ADDRSIZE-2:0]}); + + always @(posedge wclk or negedge wrst_n) + if (!wrst_n) + wfull <= 1'b0; + else + wfull <= wfull_val; endmodule // wptr_full From 218cea76fbed38c0d7cf41ba3ad63dd5f5277a66 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Wed, 6 Mar 2024 16:13:46 -0600 Subject: [PATCH 15/20] soc: Add testbench and integrate into regression tests --- sim/regression-wally | 22 +- sim/wally-soc.do | 94 ++++ testbench/testbench-soc.sv | 922 +++++++++++++++++++++++++++++++++++++ 3 files changed, 1034 insertions(+), 4 deletions(-) create mode 100644 sim/wally-soc.do create mode 100644 testbench/testbench-soc.sv diff --git a/sim/regression-wally b/sim/regression-wally index 42c54d016..32e1dfb55 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -34,6 +34,7 @@ coverage = '-coverage' in sys.argv fp = '-fp' in sys.argv nightly = '-nightly' in sys.argv softfloat = '-softfloat' in sys.argv +soc = '-soc' in sys.argv TestCase = namedtuple("TestCase", ['name', 'variant', 'cmd', 'grepstr']) # name: the name of this test configuration (used in printing human-readable @@ -387,10 +388,20 @@ if (softfloat): cmd="vsim > {} -c < {} -c < +# Example: do wally-batch.do rv32imc imperas-32i + +# Use this wally-batch.do file to run this example. +# Either bring up ModelSim and type the following at the "ModelSim>" prompt: +# do wally-batch.do +# or, to run from a shell, type the following at the shell prompt: +# vsim -do wally-batch.do -c +# (omit the "-c" to see the GUI while running from the shell) + +onbreak {resume} + +# create library +if [file exists wkdir/work_${1}_${2}] { + vdel -lib wkdir/work_${1}_${2} -all +} +vlib wkdir/work_${1}_${2} +# Create directory for coverage data +mkdir -p cov + +set coverage 0 +set CoverageVoptArg "" +set CoverageVsimArg "" + +# Need to be able to pass arguments to vopt. Unforunately argv does not work because +# it takes on different values if vsim and the do file are called from the command line or +# if the do file isd called from questa sim directly. This chunk of code uses the $4 through $n +# variables and compacts into a single list for passing to vopt. +set configOptions "" +set from 4 +set step 1 +set lst {} +for {set i 0} true {incr i} { + set x [expr {$i*$step + $from}] + if {$x > $argc} break + set arg [expr "$$x"] + lappend lst $arg +} + +if {$argc >= 3} { + if {$3 eq "-coverage" || ($argc >= 7 && $7 eq "-coverage")} { + set coverage 1 + set CoverageVoptArg "+cover=sbecf" + set CoverageVsimArg "-coverage" + } elseif {$3 eq "configOptions"} { + set configOptions $lst + puts $configOptions + } +} + +# compile source files +# suppress spurious warnngs about +# "Extra checking for conflicts with always_comb done at vopt time" +# because vsim will run vopt + +# default to config/rv64ic, but allow this to be overridden at the command line. For example: +# do wally-pipelined-batch.do ../config/rv32imc rv32imc + +# Compile bsg files, then wally +set bsg_dir ../soc/src/basejump_stl +vlog -lint -work wkdir/work_${1}_${2} +define+den2048Mb +define+sg5 +define+x32 +incdir+$bsg_dir/bsg_clk_gen +incdir+$bsg_dir/bsg_dmc +incdir+$bsg_dir/bsg_noc +incdir+$bsg_dir/bsg_tag +incdir+$bsg_dir/testing/bsg_dmc/lpddr_verilog_model +incdir+$bsg_dir/bsg_misc +incdir+$bsg_dir/testing/bsg_dmc/lpddr_verilog_model $bsg_dir/bsg_misc/bsg_defines.sv $bsg_dir/bsg_tag/bsg_tag_pkg.sv $bsg_dir/bsg_dmc/bsg_dmc_pkg.sv $bsg_dir/bsg_noc/bsg_noc_pkg.sv $bsg_dir/bsg_noc/bsg_mesh_router_pkg.sv $bsg_dir/bsg_noc/bsg_wormhole_router_pkg.sv $bsg_dir/*/*.sv $bsg_dir/testing/bsg_dmc/lpddr_verilog_model/*.sv -suppress 2583,2596,2605,2902,7063,8885,13286,13314,13388 +vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared +incdir+$bsg_dir/bsg_clk_gen +incdir+$bsg_dir/bsg_dmc +incdir+$bsg_dir/dmc_misc +incdir+$bsg_dir/bsg_misc +incdir+$bsg_dir/bsg_tag +incdir+$bsg_dir/testing/bsg_dmc/lpddr_verilog_model ../src/cvw.sv ../testbench/testbench-soc.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv ../soc/src/fifo/*.sv ../soc/src/*.sv -suppress 2583,2596,2605,2902,7063,8885,13286,13314,13388 + +# start and run simulation +# remove +acc flag for faster sim during regressions if there is no need to access internal signals +vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 ${configOptions} -o testbenchopt ${CoverageVoptArg} +vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3009,3829,8885 ${CoverageVsimArg} + +# power add generates the logging necessary for said generation. +# power add -r /dut/core/* +run -all +# power off -r /dut/core/* + + +if {$coverage} { + echo "Saving coverage to ${1}_${2}.ucdb" + do coverage-exclusions-rv64gc.do # beware: this assumes testing the rv64gc configuration + coverage save -instance /testbench/dut/core cov/${1}_${2}.ucdb +} + +# These aren't doing anything helpful +#profile report -calltree -file wally-calltree.rpt -cutoff 2 +#power report -all -bsaif power.saif +quit diff --git a/testbench/testbench-soc.sv b/testbench/testbench-soc.sv new file mode 100644 index 000000000..320ffad41 --- /dev/null +++ b/testbench/testbench-soc.sv @@ -0,0 +1,922 @@ +/////////////////////////////////////////// +// testbench.sv +// +// Written: David_Harris@hmc.edu 9 January 2021 +// Modified: +// +// Purpose: Wally Testbench and helper modules +// Applies test programs from the riscv-arch-test and Imperas suites +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "config.vh" +`include "tests.vh" +`include "BranchPredictorType.vh" + +`ifdef USE_IMPERAS_DV + `include "idv/idv.svh" +`endif + +import cvw::*; + +module testbench; + /* verilator lint_off WIDTHTRUNC */ + /* verilator lint_off WIDTHEXPAND */ + parameter DEBUG=0; + parameter string TEST="arch64m"; + parameter PrintHPMCounters=0; + parameter BPRED_LOGGER=0; + parameter I_CACHE_ADDR_LOGGER=0; + parameter D_CACHE_ADDR_LOGGER=0; + parameter RISCV_DIR = "/opt/riscv"; + parameter INSTR_LIMIT = 0; + + `ifdef USE_IMPERAS_DV + import idvPkg::*; + import rvviApiPkg::*; + import idvApiPkg::*; + `endif + +`include "parameter-defs.vh" + + logic clk; + logic reset_ext, reset; + logic ResetMem; + + // DUT signals + logic [P.AHBW-1:0] HRDATAEXT; + logic HREADYEXT, HRESPEXT; + logic HSELEXTSDC; + logic [P.PA_BITS-1:0] HADDR; + logic [P.AHBW-1:0] HWDATA; + logic [P.XLEN/8-1:0] HWSTRB; + logic HWRITE; + logic [2:0] HSIZE; + logic [2:0] HBURST; + logic [3:0] HPROT; + logic [1:0] HTRANS; + logic HMASTLOCK; + logic HCLK, HRESETn; + + logic [31:0] GPIOIN, GPIOOUT, GPIOEN; + logic UARTSin, UARTSout; + logic SPIIn, SPIOut; + logic [3:0] SPICS; + logic SDCIntr; + + logic HREADY; + logic HSELEXT; + + + string ProgramAddrMapFile, ProgramLabelMapFile; + integer ProgramAddrLabelArray [string]; + + int test, i, errors, totalerrors; + + string outputfile; + integer outputFilePointer; + + string tests[]; + logic DCacheFlushDone, DCacheFlushStart; + logic riscofTest; + logic Validate; + logic SelectTest; + logic TestComplete; + + // pick tests based on modes supported + initial begin + $display("TEST is %s", TEST); + //tests = '{}; + if (P.XLEN == 64) begin // RV64 + case (TEST) + "arch64i": tests = arch64i; + "arch64priv": tests = arch64priv; + "arch64c": if (P.C_SUPPORTED) + if (P.ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv}; + else tests = {arch64c}; + "arch64m": if (P.M_SUPPORTED) tests = arch64m; + "arch64a": if (P.A_SUPPORTED) tests = arch64a; + "arch64f": if (P.F_SUPPORTED) tests = arch64f; + "arch64d": if (P.D_SUPPORTED) tests = arch64d; + "arch64f_fma": if (P.F_SUPPORTED) tests = arch64f_fma; + "arch64d_fma": if (P.D_SUPPORTED) tests = arch64d_fma; + "arch64f_divsqrt": if (P.F_SUPPORTED) tests = arch64f_divsqrt; + "arch64d_divsqrt": if (P.D_SUPPORTED) tests = arch64d_divsqrt; + "arch64zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch64zifencei; + "arch64zicond": if (P.ZICOND_SUPPORTED) tests = arch64zicond; + "imperas64i": tests = imperas64i; + "imperas64f": if (P.F_SUPPORTED) tests = imperas64f; + "imperas64d": if (P.D_SUPPORTED) tests = imperas64d; + "imperas64m": if (P.M_SUPPORTED) tests = imperas64m; + "wally64a": if (P.A_SUPPORTED) tests = wally64a; + "imperas64c": if (P.C_SUPPORTED) tests = imperas64c; + else tests = imperas64iNOc; + "custom": tests = custom; + "wally64i": tests = wally64i; + "wally64priv": tests = wally64priv; + "wally64periph": tests = wally64periph; + "coremark": tests = coremark; + "fpga": tests = fpga; + "ahb64" : tests = ahb64; + "coverage64gc" : tests = coverage64gc; + "arch64zba": if (P.ZBA_SUPPORTED) tests = arch64zba; + "arch64zbb": if (P.ZBB_SUPPORTED) tests = arch64zbb; + "arch64zbc": if (P.ZBC_SUPPORTED) tests = arch64zbc; + "arch64zbs": if (P.ZBS_SUPPORTED) tests = arch64zbs; + "arch64zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch64zicboz; + "arch64zcb": if (P.ZCB_SUPPORTED) tests = arch64zcb; + "arch64zfh": if (P.ZFH_SUPPORTED) tests = arch64zfh; + "arch64zfh_fma": if (P.ZFH_SUPPORTED) tests = arch64zfh_fma; + "arch64zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch64zfh_divsqrt; + "arch64zfaf": if (P.ZFA_SUPPORTED) tests = arch64zfaf; + "arch64zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch64zfad; + "buildroot": tests = buildroot; + endcase + end else begin // RV32 + case (TEST) + "arch32e": tests = arch32e; + "arch32i": tests = arch32i; + "arch32priv": tests = arch32priv; + "arch32c": if (P.C_SUPPORTED) + if (P.ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv}; + else tests = {arch32c}; + "arch32m": if (P.M_SUPPORTED) tests = arch32m; + "arch32a": if (P.A_SUPPORTED) tests = arch32a; + "arch32f": if (P.F_SUPPORTED) tests = arch32f; + "arch32d": if (P.D_SUPPORTED) tests = arch32d; + "arch32f_fma": if (P.F_SUPPORTED) tests = arch32f_fma; + "arch32d_fma": if (P.D_SUPPORTED) tests = arch32d_fma; + "arch32f_divsqrt": if (P.F_SUPPORTED) tests = arch32f_divsqrt; + "arch32d_divsqrt": if (P.D_SUPPORTED) tests = arch32d_divsqrt; + "arch32zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch32zifencei; + "arch32zicond": if (P.ZICOND_SUPPORTED) tests = arch32zicond; + "imperas32i": tests = imperas32i; + "imperas32f": if (P.F_SUPPORTED) tests = imperas32f; + "imperas32m": if (P.M_SUPPORTED) tests = imperas32m; + "wally32a": if (P.A_SUPPORTED) tests = wally32a; + "imperas32c": if (P.C_SUPPORTED) tests = imperas32c; + else tests = imperas32iNOc; + "wally32i": tests = wally32i; + "wally32priv": tests = wally32priv; + "wally32periph": tests = wally32periph; + "ahb32" : tests = ahb32; + "embench": tests = embench; + "coremark": tests = coremark; + "arch32zba": if (P.ZBA_SUPPORTED) tests = arch32zba; + "arch32zbb": if (P.ZBB_SUPPORTED) tests = arch32zbb; + "arch32zbc": if (P.ZBC_SUPPORTED) tests = arch32zbc; + "arch32zbs": if (P.ZBS_SUPPORTED) tests = arch32zbs; + "arch32zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch32zicboz; + "arch32zcb": if (P.ZCB_SUPPORTED) tests = arch32zcb; + "arch32zfh": if (P.ZFH_SUPPORTED) tests = arch32zfh; + "arch32zfh_fma": if (P.ZFH_SUPPORTED) tests = arch32zfh_fma; + "arch32zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch32zfh_divsqrt; + "arch32zfaf": if (P.ZFA_SUPPORTED) tests = arch32zfaf; + "arch32zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch32zfad; + endcase + end + if (tests.size() == 0) begin + $display("TEST %s not supported in this configuration", TEST); + $finish; + end + end // initial begin + + // Model the testbench as an fsm. + // Do this in parts so it easier to verify + // part 1: build a version which echos the same behavior as the below code, but does not drive anything + // part 2: drive some of the controls + // part 3: drive all logic and remove old inital and always @ negedge clk block + + typedef enum logic [3:0]{STATE_TESTBENCH_RESET, + STATE_INIT_TEST, + STATE_RESET_MEMORIES, + STATE_RESET_MEMORIES2, + STATE_LOAD_MEMORIES, + STATE_RESET_TEST, + STATE_RUN_TEST, + STATE_COPY_RAM, + STATE_CHECK_TEST, + STATE_CHECK_TEST_WAIT, + STATE_VALIDATE, + STATE_INCR_TEST} statetype; + statetype CurrState, NextState; + logic TestBenchReset; + logic [2:0] ResetCount, ResetThreshold; + logic LoadMem; + logic ResetCntEn; + logic ResetCntRst; + logic CopyRAM; + + string signame, memfilename, bootmemfilename, pathname; + integer begin_signature_addr, end_signature_addr, signature_size; + + assign ResetThreshold = 3'd5; + + initial begin + TestBenchReset = 1; + # 100; + TestBenchReset = 0; + end + + always_ff @(posedge clk) + if (TestBenchReset) CurrState <= #1 STATE_TESTBENCH_RESET; + else CurrState <= #1 NextState; + + // fsm next state logic + always_comb begin + // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests + // and tests[0] == "2" refers to WallyRiscvArchTests + riscofTest = tests[0] == "1" | tests[0] == "2"; + pathname = tvpaths[tests[0].atoi()]; + + case(CurrState) + STATE_TESTBENCH_RESET: NextState = STATE_INIT_TEST; + STATE_INIT_TEST: NextState = STATE_RESET_MEMORIES; + STATE_RESET_MEMORIES: NextState = STATE_RESET_MEMORIES2; + STATE_RESET_MEMORIES2: NextState = STATE_LOAD_MEMORIES; // Give the reset enough time to ensure the bus is reset before loading the memories. + STATE_LOAD_MEMORIES: NextState = STATE_RESET_TEST; + STATE_RESET_TEST: if(ResetCount < ResetThreshold) NextState = STATE_RESET_TEST; + else NextState = STATE_RUN_TEST; + STATE_RUN_TEST: if(TestComplete) NextState = STATE_COPY_RAM; + else NextState = STATE_RUN_TEST; + STATE_COPY_RAM: NextState = STATE_CHECK_TEST; + STATE_CHECK_TEST: if (DCacheFlushDone) NextState = STATE_VALIDATE; + else NextState = STATE_CHECK_TEST_WAIT; + STATE_CHECK_TEST_WAIT: if(DCacheFlushDone) NextState = STATE_VALIDATE; + else NextState = STATE_CHECK_TEST_WAIT; + STATE_VALIDATE: NextState = STATE_INIT_TEST; + STATE_INCR_TEST: NextState = STATE_INIT_TEST; + default: NextState = STATE_TESTBENCH_RESET; + endcase + end // always_comb + // fsm output control logic + assign reset_ext = CurrState == STATE_TESTBENCH_RESET | CurrState == STATE_INIT_TEST | + CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2 | + CurrState == STATE_LOAD_MEMORIES | CurrState ==STATE_RESET_TEST; + // this initialization is very expensive, only do it for coremark. + assign ResetMem = (CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2) & TEST == "coremark"; + assign LoadMem = CurrState == STATE_LOAD_MEMORIES; + assign ResetCntRst = CurrState == STATE_INIT_TEST; + assign ResetCntEn = CurrState == STATE_RESET_TEST; + assign Validate = CurrState == STATE_VALIDATE; + assign SelectTest = CurrState == STATE_INIT_TEST; + assign CopyRAM = TestComplete & CurrState == STATE_RUN_TEST; + assign DCacheFlushStart = CurrState == STATE_COPY_RAM; + + // fsm reset counter + counter #(3) RstCounter(clk, ResetCntRst, ResetCntEn, ResetCount); + + //////////////////////////////////////////////////////////////////////////////// + // Find the test vector files and populate the PC to function label converter + //////////////////////////////////////////////////////////////////////////////// + logic [P.XLEN-1:0] testadr; + assign begin_signature_addr = ProgramAddrLabelArray["begin_signature"]; + assign end_signature_addr = ProgramAddrLabelArray["sig_end_canary"]; + assign signature_size = end_signature_addr - begin_signature_addr; + always @(posedge clk) begin + if(SelectTest) begin + if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"}; + else if(TEST == "buildroot") begin + memfilename = {RISCV_DIR, "/linux-testvectors/ram.bin"}; + bootmemfilename = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; + end + else memfilename = {pathname, tests[test], ".elf.memfile"}; + if (riscofTest) begin + ProgramAddrMapFile = {pathname, tests[test], "/ref/ref.elf.objdump.addr"}; + ProgramLabelMapFile = {pathname, tests[test], "/ref/ref.elf.objdump.lab"}; + end else if (TEST == "buildroot") begin + ProgramAddrMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.addr"}; + ProgramLabelMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.lab"}; + end else begin + ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"}; + ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; + end + // declare memory labels that interest us, the updateProgramAddrLabelArray task will find + // the addr of each label and fill the array. To expand, add more elements to this array + // and initialize them to zero (also initilaize them to zero at the start of the next test) + updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray); + end + + //////////////////////////////////////////////////////////////////////////////// + // Verify the test ran correctly by checking the memory against a known signature. + //////////////////////////////////////////////////////////////////////////////// + if(TestBenchReset) test = 1; + if (TEST == "coremark") + if (dut.core.priv.priv.EcallFaultM) begin + $display("Benchmark: coremark is done."); + $stop; + end + if(Validate) begin + if (TEST == "embench") begin + // Writes contents of begin_signature to .sim.output file + // this contains instret and cycles for start and end of test run, used by embench + // python speed script to calculate embench speed score. + // also, begin_signature contains the results of the self checking mechanism, + // which will be read by the python script for error checking + $display("Embench Benchmark: %s is done.", tests[test]); + if (riscofTest) outputfile = {pathname, tests[test], "/ref/ref.sim.output"}; + else outputfile = {pathname, tests[test], ".sim.output"}; + outputFilePointer = $fopen(outputfile, "w"); + i = 0; + testadr = ($unsigned(begin_signature_addr))/(P.XLEN/8); + while ($unsigned(i) < $unsigned(5'd5)) begin + $fdisplayh(outputFilePointer, DCacheFlushFSM.ShadowRAM[testadr+i]); + i = i + 1; + end + $fclose(outputFilePointer); + $display("Embench Benchmark: created output file: %s", outputfile); + end else if (TEST == "coverage64gc") begin + $display("Coverage tests don't get checked"); + end else begin + // for tests with no self checking mechanism, read .signature.output file and compare to check for errors + // clear signature to prevent contamination from previous tests + if (!begin_signature_addr) + $display("begin_signature addr not found in %s", ProgramLabelMapFile); + else if (TEST != "embench") begin // *** quick hack for embench. need a better long term solution + CheckSignature(pathname, tests[test], riscofTest, begin_signature_addr, errors); + if(errors > 0) totalerrors = totalerrors + 1; + end + end + test = test + 1; // *** this probably needs to be moved. + if (test == tests.size()) begin + if (totalerrors == 0) $display("SUCCESS! All tests ran without failures."); + else $display("FAIL: %d test programs had errors", totalerrors); + $stop; // if this is changed to $finish, wally-batch.do does not go to the next step to run coverage + end + end + end + + + //////////////////////////////////////////////////////////////////////////////// + // load memories with program image + //////////////////////////////////////////////////////////////////////////////// + + integer ShadowIndex; + integer LogXLEN; + integer StartIndex; + integer EndIndex; + integer BaseIndex; + integer memFile; + integer readResult; + if (P.SDC_SUPPORTED) begin + always @(posedge clk) begin + if (LoadMem) begin + string romfilename, sdcfilename; + romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"}; + sdcfilename = {"../testbench/sdc/ramdisk2.hex"}; + //$readmemh(romfilename, dut.uncore.uncore.bootrom.bootrom.memory.ROM); + //$readmemh(sdcfilename, sdcard.sdcard.FLASHmem); + // shorten sdc timers for simulation + //dut.uncore.uncore.sdc.SDC.LimitTimers = 1; + end + end + end else if (P.IROM_SUPPORTED) begin + always @(posedge clk) begin + if (LoadMem) begin + $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM); + end + end + end else if (P.BUS_SUPPORTED) begin : bus_supported + always @(posedge clk) begin + if (LoadMem) begin + if (TEST == "buildroot") begin + memFile = $fopen(bootmemfilename, "rb"); + readResult = $fread(dut.uncore.uncore.bootrom.bootrom.memory.ROM, memFile); + $fclose(memFile); + memFile = $fopen(memfilename, "rb"); + readResult = $fread(dut.uncore.uncore.ram.ram.memory.RAM, memFile); + $fclose(memFile); + end else + $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); + if (TEST == "embench") $display("Read memfile %s", memfilename); + end + if (CopyRAM) begin + LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64 + StartIndex = begin_signature_addr >> LogXLEN; + EndIndex = (end_signature_addr >> LogXLEN) + 8; + BaseIndex = P.UNCORE_RAM_BASE >> LogXLEN; + for(ShadowIndex = StartIndex; ShadowIndex <= EndIndex; ShadowIndex++) begin + testbench.DCacheFlushFSM.ShadowRAM[ShadowIndex] = dut.uncore.uncore.ram.ram.memory.RAM[ShadowIndex - BaseIndex]; + end + end + end + end + if (P.DTIM_SUPPORTED) begin + always @(posedge clk) begin + if (LoadMem) begin + $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM); + $display("Read memfile %s", memfilename); + end + if (CopyRAM) begin + LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64 + StartIndex = begin_signature_addr >> LogXLEN; + EndIndex = (end_signature_addr >> LogXLEN) + 8; + BaseIndex = P.UNCORE_RAM_BASE >> LogXLEN; + for(ShadowIndex = StartIndex; ShadowIndex <= EndIndex; ShadowIndex++) begin + testbench.DCacheFlushFSM.ShadowRAM[ShadowIndex] = dut.core.lsu.dtim.dtim.ram.RAM[ShadowIndex - BaseIndex]; + end + end + end + end + + integer adrindex; + if (P.UNCORE_RAM_SUPPORTED) + always @(posedge clk) + if (ResetMem) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory) + for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1) + dut.uncore.uncore.ram.ram.memory.RAM[adrindex] = '0; + + //////////////////////////////////////////////////////////////////////////////// + // Actual hardware + //////////////////////////////////////////////////////////////////////////////// + + // instantiate device to be tested + assign GPIOIN = 0; + assign UARTSin = 1; + assign SPIIn = 0; + + // Use bsg_dmc memory controller and LPDDR model + + logic ddr_ck_p; + logic ddr_ck_n; + logic ddr_cke; + logic [2:0] ddr_ba; + logic [13:0] ddr_addr; + logic ddr_cs; + logic ddr_ras; + logic ddr_cas; + logic ddr_we; + logic ddr_reset; + logic ddr_odt; + logic [P.XLEN/16-1:0] ddr_dm_oen_o; + logic [P.XLEN/16-1:0] ddr_dm; + logic [P.XLEN/16-1:0] ddr_dm_o; + logic [P.XLEN/16-1:0] ddr_dqs_p_oen_o; + logic [P.XLEN/16-1:0] ddr_dqs_p_ien_o; + logic [P.XLEN/16-1:0] ddr_dqs_p; + logic [P.XLEN/16-1:0] ddr_dqs_p_o; + logic [P.XLEN/16-1:0] ddr_dqs_p_i; + logic [P.XLEN/16-1:0] ddr_dqs_n_oen_o; + logic [P.XLEN/16-1:0] ddr_dqs_n_ien_o; + logic [P.XLEN/16-1:0] ddr_dqs_n; + logic [P.XLEN/16-1:0] ddr_dqs_n_o; + logic [P.XLEN/16-1:0] ddr_dqs_n_i; + logic [P.XLEN/2-1:0] ddr_dq_oen_o; + logic [P.XLEN/2-1:0] ddr_dq; + logic [P.XLEN/2-1:0] ddr_dq_o; + logic [P.XLEN/2-1:0] ddr_dq_i; + logic dfi_clk_2x_i; + logic dfi_clk_1x_o; + + bsg_dmc_ahb #(28, P.XLEN, 32) bsg_mem_controller ( + .HCLK, .HRESETn, .HSEL(HSELEXT), + .HADDR(HADDR[27:0]), .HWDATA, .HWSTRB, // FIXME: Double check that these are the right address bits + .HWRITE, .HTRANS, .HREADY(HREADYEXT), + .HRDATA(HRDATAEXT), .HRESP(HRESPEXT), .HREADYOUT(HREADYEXT), + .ddr_ck_p, .ddr_ck_n, .ddr_cke, .ddr_ba, .ddr_addr, + .ddr_cs, .ddr_ras, .ddr_cas, .ddr_we, .ddr_reset, .ddr_odt, + .ddr_dm_oen(ddr_dm_oen_o), .ddr_dm(ddr_dm_o), + .ddr_dqs_p_oen(ddr_dqs_p_oen_o), .ddr_dqs_p_ien(ddr_dqs_p_ien_o), + .ddr_dqs_p_out(ddr_dqs_p_o), .ddr_dqs_p_in(ddr_dqs_p_i), + .ddr_dqs_n_oen(ddr_dqs_n_oen_o), .ddr_dqs_n_ien(ddr_dqs_n_ien_o), + .ddr_dqs_n_out(ddr_dqs_n_o), .ddr_dqs_n_in(ddr_dqs_n_i), + .ddr_dq_oen(ddr_dq_oen_o), .ddr_dq_out(ddr_dq_o), .ddr_dq_in(ddr_dq_i), + .dfi_clk_2x(dfi_clk_2x_i), .dfi_clk_1x(dfi_clk_1x_o)); + + genvar ddr_i; + generate + for(ddr_i = 0; ddr_i < (P.XLEN/16); ddr_i++) begin: dm_io + assign ddr_dm[ddr_i] = !ddr_dm_oen_o[ddr_i]? ddr_dm_o[ddr_i]: 1'bz; + end + for(ddr_i = 0; ddr_i < (P.XLEN/16); ddr_i++) begin: dqs_io + assign ddr_dqs_p[ddr_i] = !ddr_dqs_p_oen_o[ddr_i]? ddr_dqs_p_o[ddr_i]: 1'bz; + assign ddr_dqs_p_i[ddr_i] = !ddr_dqs_p_ien_o[ddr_i]? ddr_dqs_p[ddr_i]: 1'b0; + assign ddr_dqs_n[ddr_i] = !ddr_dqs_n_oen_o[ddr_i]? ddr_dqs_n_o[ddr_i]: 1'bz; + assign ddr_dqs_n_i[ddr_i] = !ddr_dqs_n_ien_o[ddr_i]? ddr_dqs_n[ddr_i]: 1'b1; + end + for(ddr_i = 0; ddr_i < (P.XLEN/2); ddr_i++) begin: dq_io + assign ddr_dq[ddr_i] = !ddr_dq_oen_o[ddr_i]? ddr_dq_o[ddr_i]: 1'bz; + assign ddr_dq_i[ddr_i] = ddr_dq[ddr_i]; + end + for(ddr_i = 0; ddr_i < 1; ddr_i++) begin: lpddr + mobile_ddr mobile_ddr_inst + (.Dq (ddr_dq[32*ddr_i+31:32*ddr_i]) + ,.Dqs (ddr_dqs_p[4*ddr_i+3:4*ddr_i]) + ,.Addr (ddr_addr[13:0]) + ,.Ba (ddr_ba[1:0]) + ,.Clk (ddr_ck_p) + ,.Clk_n (ddr_ck_n) + ,.Cke (ddr_cke) + ,.Cs_n (ddr_cs) + ,.Ras_n (ddr_ras) + ,.Cas_n (ddr_cas) + ,.We_n (ddr_we) + ,.Dm (ddr_dm[4*ddr_i+3:4*ddr_i])); + end + endgenerate + + if(P.SDC_SUPPORTED) begin : sdcard + // *** fix later +/* -----\/----- EXCLUDED -----\/----- + sdModel sdcard + (.sdClk(SDCCLK), + .cmd(SDCCmd), + .dat(SDCDat)); + + assign SDCCmd = SDCCmdOE ? SDCCmdOut : 1'bz; + assign SDCCmdIn = SDCCmd; + assign SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i; + assign SDCDatIn = SDCDat; + -----/\----- EXCLUDED -----/\----- */ + assign SDCIntr = '0; + end else begin + assign SDCIntr = '0; + end + + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, + .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, + .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, + .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS); + + // generate clock to sequence tests + always begin + clk = 1; # 5; clk = 0; # 5; + end + + /* + // Print key info each cycle for debugging + always @(posedge clk) begin + #2; + $display("PCM: %x InstrM: %x (%5s) WriteDataM: %x IEUResultM: %x", + dut.core.PCM, dut.core.InstrM, InstrMName, dut.core.WriteDataM, dut.core.ieu.dp.IEUResultM); + end + */ + + //////////////////////////////////////////////////////////////////////////////// + // Support logic + //////////////////////////////////////////////////////////////////////////////// + + // Duplicate copy of pipeline registers that are optimized out of some configurations + logic [31:0] NextInstrE, InstrM; + mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); + flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); + + // Track names of instructions + string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; + logic [31:0] InstrW; + flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW); + instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, + dut.core.ifu.InstrRawF[31:0], + dut.core.ifu.InstrD, dut.core.ifu.InstrE, + InstrM, InstrW, + InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); + + // watch for problems such as lockup, reading unitialized memory, bad configs + watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck + ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, + dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName); + riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration + loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER) + loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename); + + // track the current function or global label + if (DEBUG == 1 | ((PrintHPMCounters | BPRED_LOGGER) & P.ZICNTR_SUPPORTED)) begin : FunctionName + FunctionName #(P) FunctionName(.reset(reset_ext | TestBenchReset), + .clk(clk), .ProgramAddrMapFile(ProgramAddrMapFile), .ProgramLabelMapFile(ProgramLabelMapFile)); + end + + + // Termination condition + // terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed + // or sw gp,-56(t0) for new Imperas tests + // or sd gp, -56(t0) + // or on a jump to self infinite loop (6f) for RISC-V Arch tests + logic ecf; // remove this once we don't rely on old Imperas tests with Ecalls + if (P.ZICSR_SUPPORTED) assign ecf = dut.core.priv.priv.EcallFaultM; + else assign ecf = 0; + assign TestComplete = ecf & + (dut.core.ieu.dp.regf.rf[3] == 1 | + (dut.core.ieu.dp.regf.we3 & + dut.core.ieu.dp.regf.a3 == 3 & + dut.core.ieu.dp.regf.wd3 == 1)) | + ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | + ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); + //assign DCacheFlushStart = TestComplete; + + DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone)); + + if(P.ZICSR_SUPPORTED & INSTR_LIMIT != 0) begin + logic [P.XLEN-1:0] Minstret; + assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + always @(negedge clk) begin + if((Minstret != 0) && (Minstret % 'd100000 == 0)) $display("Reached %d instructions", Minstret); + if((Minstret == INSTR_LIMIT) & (INSTR_LIMIT!=0)) begin $stop; $stop; end + end +end + + //////////////////////////////////////////////////////////////////////////////// + // ImperasDV Co-simulator hooks + //////////////////////////////////////////////////////////////////////////////// +`ifdef USE_IMPERAS_DV + + rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi(); + wallyTracer #(P) wallyTracer(rvvi); + + trace2log idv_trace2log(rvvi); + // trace2cov idv_trace2cov(rvvi); + + // enabling of comparison types + trace2api #(.CMP_PC (1), + .CMP_INS (1), + .CMP_GPR (1), + .CMP_FPR (1), + .CMP_VR (0), + .CMP_CSR (1) + ) idv_trace2api(rvvi); + + initial begin + int iter; + #1; + IDV_MAX_ERRORS = 3; + + // Initialize REF (do this before initializing the DUT) + if (!rvviVersionCheck(RVVI_API_VERSION)) begin + $display($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION)); + $fatal; + end + + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org")); + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv")); + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC")); + void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56)); + void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6)); + + if (!rvviRefInit("")) begin + $display($sformatf("%m @ t=%0t: rvviRefInit failed", $time)); + $fatal; + end + + // Volatile CSRs + void'(rvviRefCsrSetVolatile(0, 32'hC00)); // CYCLE + void'(rvviRefCsrSetVolatile(0, 32'hB00)); // MCYCLE + void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET + void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET + void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME + + // User HPMCOUNTER3 - HPMCOUNTER31 + for (iter='hC03; iter<='hC1F; iter++) begin + void'(rvviRefCsrSetVolatile(0, iter)); // HPMCOUNTERx + end + + // Machine MHPMCOUNTER3 - MHPMCOUNTER31 + for (iter='hB03; iter<='hB1F; iter++) begin + void'(rvviRefCsrSetVolatile(0, iter)); // MHPMCOUNTERx + end + + // cannot predict this register due to latency between + // pending and taken + void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP + void'(rvviRefCsrSetVolatile(0, 32'h144)); // SIP + + // Privileges for PMA are set in the imperas.ic + // volatile (IO) regions are defined here + // only real ROM/RAM areas are BOOTROM and UNCORE_RAM + if (P.CLINT_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.CLINT_BASE, (P.CLINT_BASE + P.CLINT_RANGE))); + end + if (P.GPIO_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.GPIO_BASE, (P.GPIO_BASE + P.GPIO_RANGE))); + end + if (P.UART_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.UART_BASE, (P.UART_BASE + P.UART_RANGE))); + end + if (P.PLIC_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.PLIC_BASE, (P.PLIC_BASE + P.PLIC_RANGE))); + end + if (P.SDC_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.SDC_BASE, (P.SDC_BASE + P.SDC_RANGE))); + end + if (P.SPI_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.SPI_BASE, (P.SPI_BASE + P.SPI_RANGE))); + end + + if(P.XLEN==32) begin + void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH + void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH + end + + void'(rvviRefCsrSetVolatile(0, 32'h104)); // SIE - Temporary!!!! + + // Load memory + // *** RT: This section can probably be moved into the same chunk of code which + // loads the memories. However I'm not sure that ImperasDV supports reloading + // the memories without relaunching the simulator. + begin + longint x64; + int x32[2]; + longint index; + string memfilenameImperasDV, bootmemfilenameImperasDV; + + memfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/ram.bin"}; + bootmemfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; + + $display("RVVI Loading bootmem.bin"); + memFile = $fopen(bootmemfilenameImperasDV, "rb"); + index = 'h1000 - 8; + while(!$feof(memFile)) begin + index+=8; + readResult = $fread(x64, memFile); + if (x64 == 0) continue; + x32[0] = x64 & 'hffffffff; + x32[1] = x64 >> 32; + rvviRefMemoryWrite(0, index+0, x32[0], 4); + rvviRefMemoryWrite(0, index+4, x32[1], 4); + //$display("boot %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); + end + $fclose(memFile); + + $display("RVVI Loading ram.bin"); + memFile = $fopen(memfilenameImperasDV, "rb"); + index = 'h80000000 - 8; + while(!$feof(memFile)) begin + index+=8; + readResult = $fread(x64, memFile); + if (x64 == 0) continue; + x32[0] = x64 & 'hffffffff; + x32[1] = x64 >> 32; + rvviRefMemoryWrite(0, index+0, x32[0], 4); + rvviRefMemoryWrite(0, index+4, x32[1], 4); + //$display("ram %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); + end + $fclose(memFile); + + $display("RVVI Loading Complete"); + + void'(rvviRefPcSet(0, P.RESET_VECTOR)); // set BOOTROM address + end + end + + always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5])); + + final begin + void'(rvviRefShutdown()); + end + +`endif + //////////////////////////////////////////////////////////////////////////////// + // END of ImperasDV Co-simulator hooks + //////////////////////////////////////////////////////////////////////////////// + + task automatic CheckSignature; + // This task must be declared inside this module as it needs access to parameter P. There is + // no way to pass P to the task unless we convert it to a module. + + input string pathname; + input string TestName; + input logic riscofTest; + input integer begin_signature_addr; + output integer errors; + int fd, code; + string line; + int siglines, sigentries; + + localparam SIGNATURESIZE = 5000000; + integer i; + logic [31:0] sig32[0:SIGNATURESIZE]; + logic [31:0] parsed; + logic [P.XLEN-1:0] signature[0:SIGNATURESIZE]; + string signame; + logic [P.XLEN-1:0] testadr, testadrNoBase; + + // read .signature.output file and compare to check for errors + if (riscofTest) signame = {pathname, TestName, "/ref/Reference-sail_c_simulator.signature"}; + else signame = {pathname, TestName, ".signature.output"}; + + // read signature file from memory and count lines. Can't use readmemh because we need the line count + // $readmemh(signame, sig32); + fd = $fopen(signame, "r"); + siglines = 0; + if (fd == 0) $display("Unable to read %s", signame); + else begin + while (!$feof(fd)) begin + code = $fgets(line, fd); + if (code != 0) begin + int errno; + string errstr; + errno = $ferror(fd, errstr); + if (errno != 0) $display("Error %d (code %d) reading line %d of %s: %s", errno, code, siglines, signame, errstr); + if (line.len() > 1) begin // skip blank lines + if ($sscanf(line, "%x", parsed) != 0) begin + sig32[siglines] = parsed; + siglines = siglines + 1; // increment if line is not blank + end + end + end + end + $fclose(fd); + end + + // Check valid number of lines were read + if (siglines == 0) begin + errors = 1; + $display("Error: empty test file %s", signame); + end else if (P.XLEN == 64 & (siglines % 2)) begin + errors = 1; + $display("Error: RV64 signature has odd number of lines %s", signame); + end else errors = 0; + + // copy lines into signature, converting to XLEN if necessary + sigentries = (P.XLEN == 32) ? siglines : siglines/2; // number of signature entries + for (i=0; i Date: Mon, 11 Mar 2024 13:04:59 -0500 Subject: [PATCH 16/20] soc/src: Add script to sparse-checkout the bsg_dmc files --- soc/src/setup_basejump.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 soc/src/setup_basejump.sh diff --git a/soc/src/setup_basejump.sh b/soc/src/setup_basejump.sh new file mode 100755 index 000000000..02c1fbad7 --- /dev/null +++ b/soc/src/setup_basejump.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +git submodule update --init +cd basejump_stl + +rm -rf imports +git sparse-checkout set bsg_async bsg_clk_gen bsg_dataflow bsg_dmc bsg_mem bsg_misc bsg_noc bsg_tag testing/bsg_dmc/lpddr_verilog_model +rm -f */*_nonsynth_* + +# Fix errors in basejump code +printf '69m63\nw\n' | ed bsg_mem/bsg_mem_1rw_sync_mask_write_bit_from_1r1w.sv +sed -i '17i \`include "bsg_defines.sv"' bsg_dmc/bsg_dmc_dly_line_v3.sv From 8a82137c0d2a6029a881dc96ada77a371a6cf75f Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Mon, 11 Mar 2024 13:09:10 -0500 Subject: [PATCH 17/20] sim/regression-wally: Exclude zfh tests from soc config --- sim/regression-wally | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sim/regression-wally b/sim/regression-wally index 32e1dfb55..9ae8268e4 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -395,6 +395,8 @@ if (soc): configs = [] # Delete all configs, just use test64gc coverStr = '-coverage' # Include coverage report for test in tests64gc: + if 'zfh' in test: + continue # Skip zfh tests tc = TestCase( name=test, variant="rv64gc", From 5c05ec142382558dbd097cb11d38cb9b283a0fc0 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Mon, 11 Mar 2024 16:26:26 -0500 Subject: [PATCH 18/20] sim/regression-wally: Exclude zfa tests from soc --- sim/regression-wally | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sim/regression-wally b/sim/regression-wally index 9ae8268e4..fdfe6a220 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -395,8 +395,8 @@ if (soc): configs = [] # Delete all configs, just use test64gc coverStr = '-coverage' # Include coverage report for test in tests64gc: - if 'zfh' in test: - continue # Skip zfh tests + if any(s in test for s in ['zfa', 'zfh']): + continue # Skip zfa and zfh tests tc = TestCase( name=test, variant="rv64gc", From b6bfe95930468792397e49116768f9aa52808d0e Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Mon, 11 Mar 2024 16:27:08 -0500 Subject: [PATCH 19/20] soc/src/setup_basejump.sh: Fix basejump setup script for fresh init each time --- soc/src/setup_basejump.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/soc/src/setup_basejump.sh b/soc/src/setup_basejump.sh index 02c1fbad7..006248d29 100755 --- a/soc/src/setup_basejump.sh +++ b/soc/src/setup_basejump.sh @@ -1,5 +1,6 @@ #! /bin/bash +git submodule deinit -f basejump_stl git submodule update --init cd basejump_stl From ec48e11a547b632c73899812c3d1b4751fc61152 Mon Sep 17 00:00:00 2001 From: Marcus Mellor Date: Mon, 11 Mar 2024 16:49:56 -0500 Subject: [PATCH 20/20] sim/regression-wally: exclude zkn*, zbk* from soc config --- sim/regression-wally | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sim/regression-wally b/sim/regression-wally index fdfe6a220..9afcb36e4 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -395,8 +395,8 @@ if (soc): configs = [] # Delete all configs, just use test64gc coverStr = '-coverage' # Include coverage report for test in tests64gc: - if any(s in test for s in ['zfa', 'zfh']): - continue # Skip zfa and zfh tests + if any(s in test for s in ['zfa', 'zfh', 'zbk', 'zkn']): + continue # Skip tests for extensions that aren't in riscv-arch-tests yet tc = TestCase( name=test, variant="rv64gc",