diff --git a/wally-pipelined/config/busybear/wally-config.vh b/wally-pipelined/config/busybear/wally-config.vh index a3c5188f6..b01a2e30e 100644 --- a/wally-pipelined/config/busybear/wally-config.vh +++ b/wally-pipelined/config/busybear/wally-config.vh @@ -1,5 +1,5 @@ ////////////////////////////////////////// -// wally-config.vh +// busybear-config.vh // // Written: David_Harris@hmc.edu 4 January 2021 // Modified: @@ -24,6 +24,7 @@ // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /////////////////////////////////////////// +`define BUSYBEAR // RV32 or RV64: XLEN = 32 or 64 `define XLEN 64 @@ -61,14 +62,16 @@ // Peripheral memory space extends from BASE to BASE+RANGE // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits -`define TIMBASE 64'h0000000080000000 -`define TIMRANGE 64'h000000000007FFFF -`define CLINTBASE 64'h0000000002000000 -`define CLINTRANGE 64'h000000000000FFFF -`define GPIOBASE 64'h0000000010012000 -`define GPIORANGE 64'h00000000000000FF -`define UARTBASE 64'h0000000010000000 -`define UARTRANGE 64'h0000000000000007 +`define TIMBASE 32'h80000000 +`define TIMRANGE 32'h07FFFFFF +`define BOOTTIMBASE 32'h00000000 //only needs to go from 0x1000 to 0x2FFF, extending to a power of 2 +`define BOOTTIMRANGE 32'h00003FFF +`define CLINTBASE 32'h02000000 +`define CLINTRANGE 32'h0000BFFF +//`define GPIOBASE 32'h10012000 // no GPIO in linux for now +//`define GPIORANGE 32'h000000FF +`define UARTBASE 32'h10000000 +`define UARTRANGE 32'h00000007 // Bus Interface width `define AHBW 64 diff --git a/wally-pipelined/regression/sim-busybear b/wally-pipelined/regression/sim-busybear new file mode 100755 index 000000000..e20344043 --- /dev/null +++ b/wally-pipelined/regression/sim-busybear @@ -0,0 +1 @@ +vsim -do wally-busybear.do diff --git a/wally-pipelined/regression/sim-busybear-batch b/wally-pipelined/regression/sim-busybear-batch new file mode 100755 index 000000000..2c351aade --- /dev/null +++ b/wally-pipelined/regression/sim-busybear-batch @@ -0,0 +1,3 @@ +vsim -c <" prompt: -# do wally-pipelined.do ../config/rv64ic +# do wally-pipelined-batch.do # or, to run from a shell, type the following at the shell prompt: -# vsim -c -do wally-pipelined.do ../config/rv64ic +# vsim -do wally-pipelined-batch.do -c # (omit the "-c" to see the GUI while running from the shell) onbreak {resume} @@ -27,12 +26,22 @@ vlib work # suppress spurious warnngs about # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -vlog +incdir+$1 ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583 +# default to config/rv64ic, but allow this to be overridden at the command line. For example: +# do wally-pipelined-batch.do ../config/rv32ic +switch $argc { + 0 {vlog +incdir+../config/rv64ic ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583} + 1 {vlog +incdir+$1 ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583} +} # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals -vopt work.testbench -o workopt +vopt +acc work.testbench -o workopt vsim workopt +# load the branch predictors with known data. The value of the data is not important for function, but +# is important for perventing pessimistic x propagation. +mem load -infile twoBitPredictor.txt -format bin testbench/dut/hart/ifu/bpred/DirPredictor/memory/memory +mem load -infile BTBPredictor.txt -format bin testbench/dut/hart/ifu/bpred/TargetPredictor/memory/memory + run -all quit diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index 6e56c079b..1050f710d 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -108,7 +108,7 @@ module csrm #(parameter assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT); // CSRs - flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, `RESET_VECTOR, MTVEC_REGW); + flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, `XLEN'b0, MTVEC_REGW); //busybear: changed reset value to 0 generate if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist flopenl #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK, zero, MEDELEG_REGW); @@ -125,7 +125,11 @@ module csrm #(parameter flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW); flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW); flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); + `ifndef BUSYBEAR flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], allones, MCOUNTEREN_REGW); + `else + flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW); + `endif flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], allones, MCOUNTINHIBIT_REGW); flopenr #(`XLEN) PMPADDR0reg(clk, reset, WritePMPADDR0M, CSRWriteValM, PMPADDR0_REGW); // PMPCFG registers are a pair of 64-bit in RV64 and four 32-bit in RV32 diff --git a/wally-pipelined/src/privileged/csrs.sv b/wally-pipelined/src/privileged/csrs.sv index 8f688cc1b..8b851e07e 100644 --- a/wally-pipelined/src/privileged/csrs.sv +++ b/wally-pipelined/src/privileged/csrs.sv @@ -76,13 +76,17 @@ module csrs #(parameter assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN); // CSRs - flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, `RESET_VECTOR, STVEC_REGW); + flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, zero, STVEC_REGW); //busybear: change reset to 0 flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, zero, SCAUSE_REGW); flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); + `ifndef BUSYBEAR flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], allones, SCOUNTEREN_REGW); + `else + flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW); + `endif if (`N_SUPPORTED) begin logic WriteSEDELEGM, WriteSIDELEGM; assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG); diff --git a/wally-pipelined/src/privileged/csrsr.sv b/wally-pipelined/src/privileged/csrsr.sv index ecfbecfda..40f77a12e 100644 --- a/wally-pipelined/src/privileged/csrsr.sv +++ b/wally-pipelined/src/privileged/csrsr.sv @@ -109,15 +109,15 @@ module csrsr ( if (reset) begin STATUS_SUM_INT <= 0; STATUS_MPRV_INT <= 0; // Per Priv 3.3 - STATUS_FS_INT <= 2'b01; // initial - STATUS_MPP <= `M_MODE; - STATUS_SPP <= 1'b1; - STATUS_MPIE <= 1; - STATUS_SPIE <= `S_SUPPORTED; - STATUS_UPIE <= `U_SUPPORTED; + STATUS_FS_INT <= 0; //2'b01; // busybear: change all these reset values to 0 + STATUS_MPP <= 0; //`M_MODE; + STATUS_SPP <= 0; //1'b1; + STATUS_MPIE <= 0; //1; + STATUS_SPIE <= 0; //`S_SUPPORTED; + STATUS_UPIE <= 0; // `U_SUPPORTED; STATUS_MIE <= 0; // Per Priv 3.3 - STATUS_SIE <= `S_SUPPORTED; - STATUS_UIE <= `U_SUPPORTED; + STATUS_SIE <= 0; //`S_SUPPORTED; + STATUS_UIE <= 0; //`U_SUPPORTED; end else if (~StallW) begin if (WriteMSTATUSM) begin STATUS_SUM_INT <= CSRWriteValM[18]; @@ -179,4 +179,4 @@ module csrsr ( // *** add code to track STATUS_FS_INT for dirty floating point registers end end -endmodule \ No newline at end of file +endmodule diff --git a/wally-pipelined/src/uncore/clint.sv b/wally-pipelined/src/uncore/clint.sv index 215ef7df0..71770323e 100644 --- a/wally-pipelined/src/uncore/clint.sv +++ b/wally-pipelined/src/uncore/clint.sv @@ -28,8 +28,9 @@ module clint ( input logic HCLK, HRESETn, - input logic [1:0] MemRWclint, - input logic [15:0] HADDR, + input logic HSELCLINT, + input logic [15:0] HADDR, + input logic HWRITE, input logic [`XLEN-1:0] HWDATA, output logic [`XLEN-1:0] HREADCLINT, output logic HRESPCLINT, HREADYCLINT, @@ -41,8 +42,8 @@ module clint ( logic [15:0] entry; logic memread, memwrite; - assign memread = MemRWclint[1]; - assign memwrite = MemRWclint[0]; + assign memread = HSELCLINT & ~HWRITE; + assign memwrite = HSELCLINT & HWRITE; assign HRESPCLINT = 0; // OK // assign HREADYCLINT = 1; // Respond immediately always_ff @(posedge HCLK) // delay response diff --git a/wally-pipelined/src/uncore/dtim.sv b/wally-pipelined/src/uncore/dtim.sv index 4216b356c..42ae7fbcc 100644 --- a/wally-pipelined/src/uncore/dtim.sv +++ b/wally-pipelined/src/uncore/dtim.sv @@ -25,24 +25,30 @@ `include "wally-config.vh" -module dtim ( +module dtim #(parameter BASE=0, RANGE = 65535) ( input logic HCLK, HRESETn, - input logic [1:0] MemRWtim, - input logic [18:0] HADDR, - input logic [`XLEN-1:0] HWDATA, input logic HSELTim, + input logic [31:0] HADDR, + input logic HWRITE, + input logic [`XLEN-1:0] HWDATA, output logic [`XLEN-1:0] HREADTim, output logic HRESPTim, HREADYTim ); - logic [`XLEN-1:0] RAM[0:65535]; - logic [18:0] HWADDR; + logic [`XLEN-1:0] RAM[BASE>>(1+`XLEN/32):(RANGE+BASE)>>1+(`XLEN/32)]; + logic [31:0] HWADDR, A; logic [`XLEN-1:0] HREADTim0; // logic [`XLEN-1:0] write; logic [15:0] entry; - logic memread, memwrite; - logic [3:0] busycount; + logic memread, memwrite; + logic [3:0] busycount; + + always_ff @(posedge HCLK) begin + memread <= HSELTim & ~ HWRITE; + memwrite <= HSELTim & HWRITE; + A <= HADDR; + end // busy FSM to extend READY signal always_ff @(posedge HCLK, negedge HRESETn) @@ -61,42 +67,21 @@ module dtim ( end end - /* always_ff @(posedge HCLK, negedge HRESETn) - if (~HRESETn) begin - HREADYTim <= 0; - end else begin - HREADYTim <= HSELTim; // always respond one cycle later - end */ - - - assign memread = MemRWtim[1]; - assign memwrite = MemRWtim[0]; -// always_ff @(posedge HCLK) -// memwrite <= MemRWtim[0]; // delay memwrite to write phase assign HRESPTim = 0; // OK -// assign HREADYTim = 1; // Respond immediately; *** extend this - // Model memory read and write - generate if (`XLEN == 64) begin -// always_ff @(negedge HCLK) -// if (memwrite) RAM[HWADDR[17:3]] <= HWDATA; always_ff @(posedge HCLK) begin - //if (memwrite) RAM[HADDR[17:3]] <= HWDATA; - HWADDR <= HADDR; - HREADTim0 <= RAM[HADDR[17:3]]; - if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA; + HWADDR <= A; + HREADTim0 <= RAM[A[31:3]]; + if (memwrite && HREADYTim) RAM[HWADDR[31:3]] <= HWDATA; end end else begin -// always_ff @(negedge HCLK) -// if (memwrite) RAM[HWADDR[17:2]] <= HWDATA; always_ff @(posedge HCLK) begin - //if (memwrite) RAM[HADDR[17:2]] <= HWDATA; - HWADDR <= HADDR; - HREADTim0 <= RAM[HADDR[17:2]]; - if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA; + HWADDR <= A; + HREADTim0 <= RAM[A[31:2]]; + if (memwrite && HREADYTim) RAM[HWADDR[31:2]] <= HWDATA; end end endgenerate diff --git a/wally-pipelined/src/uncore/gpio.sv b/wally-pipelined/src/uncore/gpio.sv index ffea6c72e..216e30ddf 100644 --- a/wally-pipelined/src/uncore/gpio.sv +++ b/wally-pipelined/src/uncore/gpio.sv @@ -29,9 +29,10 @@ module gpio ( input logic HCLK, HRESETn, - input logic [1:0] MemRWgpio, + input logic HSELGPIO, input logic [7:0] HADDR, input logic [`XLEN-1:0] HWDATA, + input logic HWRITE, output logic [`XLEN-1:0] HREADGPIO, output logic HRESPGPIO, HREADYGPIO, input logic [31:0] GPIOPinsIn, @@ -42,8 +43,8 @@ module gpio ( logic [7:0] entry; logic memread, memwrite; - assign memread = MemRWgpio[1]; - assign memwrite = MemRWgpio[0]; + assign memread = HSELGPIO & ~HWRITE; + assign memwrite = HSELGPIO & HWRITE; assign HRESPGPIO = 0; // OK always_ff @(posedge HCLK) // delay response to data cycle HREADYGPIO <= memread | memwrite; diff --git a/wally-pipelined/src/uncore/imem.sv b/wally-pipelined/src/uncore/imem.sv index 68ef87519..4ce2e4666 100644 --- a/wally-pipelined/src/uncore/imem.sv +++ b/wally-pipelined/src/uncore/imem.sv @@ -32,24 +32,35 @@ module imem ( output logic InstrAccessFaultF); /* verilator lint_off UNDRIVEN */ - logic [`XLEN-1:0] RAM[0:65535]; + logic [`XLEN-1:0] RAM[`TIMBASE>>(1+`XLEN/32):(`TIMRANGE+`TIMBASE)>>(1+`XLEN/32)]; + `ifdef BOOTTIMBASE + logic [`XLEN-1:0] bootram[`BOOTTIMBASE>>(1+`XLEN/32):(`BOOTTIMRANGE+`BOOTTIMBASE)>>(1+`XLEN/32)]; + `endif /* verilator lint_on UNDRIVEN */ - logic [15:0] adrbits; + logic [28:0] adrbits; logic [`XLEN-1:0] rd; // logic [15:0] rd2; generate - if (`XLEN==32) assign adrbits = AdrF[17:2]; - else assign adrbits = AdrF[18:3]; + if (`XLEN==32) assign adrbits = AdrF[30:2]; + else assign adrbits = AdrF[31:3]; endgenerate + `ifndef BOOTTIMBASE assign #2 rd = RAM[adrbits]; // word aligned + `else + assign #2 rd = (AdrF < (`TIMBASE >> 1)) ? bootram[adrbits] : RAM[adrbits]; // busybear: 2 memory options + `endif // hack right now for unaligned 32-bit instructions // eventually this will need to cause a stall like a cache miss // when the instruction wraps around a cache line // could be optimized to only stall when the instruction wrapping is 32 bits + `ifndef BOOTTIMBASE assign #2 rd2 = RAM[adrbits+1][15:0]; + `else + assign #2 rd2 = (AdrF < (`TIMBASE >> 1)) ? bootram[adrbits+1][15:0] : RAM[adrbits+1][15:0]; //busybear: 2 memory options + `endif generate if (`XLEN==32) begin assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd; @@ -57,7 +68,11 @@ module imem ( end else begin assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32]) : (AdrF[1] ? rd[47:16] : rd[31:0]); + `ifndef BOOTTIMBASE assign InstrAccessFaultF = |AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `TIMBASE | `TIMRANGE); + `else + assign InstrAccessFaultF = 0; //busybear: for now, i know we're not doing this + `endif end endgenerate endmodule diff --git a/wally-pipelined/src/uncore/uart.sv b/wally-pipelined/src/uncore/uart.sv index b4854981a..373674867 100644 --- a/wally-pipelined/src/uncore/uart.sv +++ b/wally-pipelined/src/uncore/uart.sv @@ -29,8 +29,9 @@ module uart ( input logic HCLK, HRESETn, - input logic [1:0] MemRWuart, - input logic [2:0] HADDR, + input logic HSELUART, + input logic [2:0] HADDR, + input logic HWRITE, input logic [`XLEN-1:0] HWDATA, output logic [`XLEN-1:0] HREADUART, output logic HRESPUART, HREADYUART, @@ -44,37 +45,37 @@ module uart ( logic [7:0] Din, Dout; // rename processor interface signals to match PC16550D and provide one-byte interface - assign MEMRb = ~MemRWuart[1]; - assign MEMWb = ~MemRWuart[0]; - assign A = HADDR[2:0]; + always_ff @(posedge HCLK) begin + MEMRb <= ~(HSELUART & ~HWRITE); + MEMWb <= ~(HSELUART & HWRITE); + A <= HADDR[2:0]; + end assign HRESPUART = 0; // OK - //assign HREADYUART = 1; // Respond immediately - always_ff @(posedge HCLK) // delay response to data cycle - HREADYUART <= ~MEMRb | ~MEMWb; + assign HREADYUART = 1; // should idle high during address phase and respond high when done; will need to be modified if UART ever needs more than 1 cycle to do something generate if (`XLEN == 64) begin - always @(posedge HCLK) begin + always_comb begin HREADUART = {Dout, Dout, Dout, Dout, Dout, Dout, Dout, Dout}; - case (HADDR) - 3'b000: Din <= HWDATA[7:0]; - 3'b001: Din <= HWDATA[15:8]; - 3'b010: Din <= HWDATA[23:16]; - 3'b011: Din <= HWDATA[31:24]; - 3'b100: Din <= HWDATA[39:32]; - 3'b101: Din <= HWDATA[47:40]; - 3'b110: Din <= HWDATA[55:48]; - 3'b111: Din <= HWDATA[63:56]; + case (A) + 3'b000: Din = HWDATA[7:0]; + 3'b001: Din = HWDATA[15:8]; + 3'b010: Din = HWDATA[23:16]; + 3'b011: Din = HWDATA[31:24]; + 3'b100: Din = HWDATA[39:32]; + 3'b101: Din = HWDATA[47:40]; + 3'b110: Din = HWDATA[55:48]; + 3'b111: Din = HWDATA[63:56]; endcase end end else begin // 32-bit - always @(posedge HCLK) begin + always_comb begin HREADUART = {Dout, Dout, Dout, Dout}; - case (HADDR[1:0]) - 2'b00: Din <= HWDATA[7:0]; - 2'b01: Din <= HWDATA[15:8]; - 2'b10: Din <= HWDATA[23:16]; - 2'b11: Din <= HWDATA[31:24]; + case (A[1:0]) + 2'b00: Din = HWDATA[7:0]; + 2'b01: Din = HWDATA[15:8]; + 2'b10: Din = HWDATA[23:16]; + 2'b11: Din = HWDATA[31:24]; endcase end end diff --git a/wally-pipelined/src/uncore/uartPC16550D.sv b/wally-pipelined/src/uncore/uartPC16550D.sv index d494e19f2..28b530751 100644 --- a/wally-pipelined/src/uncore/uartPC16550D.sv +++ b/wally-pipelined/src/uncore/uartPC16550D.sv @@ -376,7 +376,7 @@ module uartPC16550D( TXHR <= Din; txhrfull <= 1; end - $display("UART transmits: %c",Din); // for testbench + $write("%c",Din); // for testbench end if (txstate == UART_IDLE) begin // move data into tx shift register if available if (fifoenabled) begin diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index d899717e4..c068616c9 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -2,7 +2,7 @@ // uncore.sv // // Written: David_Harris@hmc.edu 9 January 2021 -// Modified: +// Modified: Ben Bracker 6 Mar 2021 to better fit AMBA 3 AHB-Lite spec // // Purpose: System-on-Chip components outside the core (hart) // Memories, peripherals, external bus control @@ -59,58 +59,96 @@ module uncore ( logic [`XLEN-1:0] HWDATA; logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADGPIO, HREADUART; + logic HSELTim, HSELCLINT, HSELGPIO, PreHSELUART, HSELUART; + logic HSELTimD, HSELCLINTD, HSELGPIOD, HSELUARTD; logic HRESPTim, HRESPCLINT, HRESPGPIO, HRESPUART; logic HREADYTim, HREADYCLINT, HREADYGPIO, HREADYUART; - logic [1:0] MemRW; - logic [1:0] MemRWtim, MemRWclint, MemRWgpio, MemRWuart; + `ifdef BOOTTIMBASE + logic [`XLEN-1:0] HREADBootTim; + logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim; + logic [1:0] MemRWboottim; + `endif logic UARTIntr;// *** will need to tie INTR to an interrupt handler // AHB Address decoder adrdec timdec(HADDR, `TIMBASE, `TIMRANGE, HSELTim); + `ifdef BOOTTIMBASE + adrdec boottimdec(HADDR, `BOOTTIMBASE, `BOOTTIMRANGE, HSELBootTim); + `endif adrdec clintdec(HADDR, `CLINTBASE, `CLINTRANGE, HSELCLINT); - adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO); + `ifdef GPIOBASE + adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO); + `endif adrdec uartdec(HADDR, `UARTBASE, `UARTRANGE, PreHSELUART); assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported - - // Enable read or write based on decoded address - assign MemRW = {~HWRITE, HWRITED}; - assign MemRWtim = MemRW & {2{HSELTim}}; - assign MemRWclint = MemRW & {2{HSELCLINT}}; - assign MemRWgpio = MemRW & {2{HSELGPIO}}; - assign MemRWuart = MemRW & {2{HSELUART}}; -/* always_ff @(posedge HCLK) begin - HADDRD <= HADDR; - MemRWtim <= MemRW & {2{HSELTim}}; - MemRWclint <= MemRW & {2{HSELCLINT}}; - MemRWgpio <= MemRW & {2{HSELGPIO}}; - MemRWuart <= MemRW & {2{HSELUART}}; - end */ // subword accesses: converts HWDATAIN to HWDATA subwordwrite sww(.*); // tightly integrated memory - dtim dtim(.HADDR(HADDR[18:0]), .*); + dtim #(.BASE(`TIMBASE), .RANGE(`TIMRANGE)) dtim (.*); + `ifdef BOOTTIMBASE + dtim #(.BASE(`BOOTTIMBASE), .RANGE(`BOOTTIMRANGE)) bootdtim(.HSELTim(HSELBootTim), .HREADTim(HREADBootTim), .HRESPTim(HRESPBootTim), .HREADYTim(HREADYBootTim), .*); + `endif // memory-mapped I/O peripherals clint clint(.HADDR(HADDR[15:0]), .*); + `ifdef GPIOBASE gpio gpio(.HADDR(HADDR[7:0]), .*); // *** may want to add GPIO interrupts + `endif uart uart(.HADDR(HADDR[2:0]), .TXRDYb(), .RXRDYb(), .INTR(UARTIntr), .SIN(UARTSin), .SOUT(UARTSout), .DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1), - .RTSb(), .DTRb(), .OUT1b(), .OUT2b(), .*); + .RTSb(), .DTRb(), .OUT1b(), .OUT2b(), .*); // mux could also include external memory // AHB Read Multiplexer - assign HRDATA = ({`XLEN{HSELTim}} & HREADTim) | ({`XLEN{HSELCLINT}} & HREADCLINT) | - ({`XLEN{HSELGPIO}} & HREADGPIO) | ({`XLEN{HSELUART}} & HREADUART); - assign HRESP = HSELTim & HRESPTim | HSELCLINT & HRESPCLINT | HSELGPIO & HRESPGPIO | HSELUART & HRESPUART; - assign HREADY = HSELTim & HREADYTim | HSELCLINT & HREADYCLINT | HSELGPIO & HREADYGPIO | HSELUART & HREADYUART; + assign HRDATA = ({`XLEN{HSELTimD}} & HREADTim) | ({`XLEN{HSELCLINTD}} & HREADCLINT) | + `ifdef GPIOBASE + ({`XLEN{HSELGPIOD}} & HREADGPIO) | + `endif + `ifdef BOOTTIMBASE + ({`XLEN{HSELBootTimD}} & HREADBootTim) | + `endif + ({`XLEN{HSELUARTD}} & HREADUART); + assign HRESP = HSELTimD & HRESPTim | HSELCLINTD & HRESPCLINT | + `ifdef GPIOBASE + HSELGPIOD & HRESPGPIO | + `endif + `ifdef BOOTTIMBASE + HSELBootTimD & HRESPBootTim | + `endif + HSELUARTD & HRESPUART; + assign HREADY = HSELTimD & HREADYTim | HSELCLINTD & HREADYCLINT | + `ifdef GPIOBASE + HSELGPIOD & HREADYGPIO | + `endif + `ifdef BOOTTIMBASE + HSELBootTimD & HREADYBootTim | + `endif + HSELUARTD & HREADYUART; // Faults - assign DataAccessFaultM = ~(HSELTim | HSELCLINT | HSELGPIO | HSELUART); + assign DataAccessFaultM = ~(HSELTimD | HSELCLINTD | + `ifdef GPIOBASE + HSELGPIOD | + `endif + `ifdef BOOTTIMBASE + HSELBootTimD | + `endif + HSELUARTD); - + + // Address Decoder Delay (figure 4-2 in spec) + flopr #(1) hseltimreg(HCLK, ~HRESETn, HSELTim, HSELTimD); + flopr #(1) hselclintreg(HCLK, ~HRESETn, HSELCLINT, HSELCLINTD); + `ifdef GPIOBASE + flopr #(1) hselgpioreg(HCLK, ~HRESETn, HSELGPIO, HSELGPIOD); + `endif + flopr #(1) hseluartreg(HCLK, ~HRESETn, HSELUART, HSELUARTD); + `ifdef BOOTTIMBASE + flopr #(1) hselboottimreg(HCLK, ~HRESETn, HSELBootTim, HSELBootTimD); + `endif endmodule diff --git a/wally-pipelined/testbench/testbench-busybear.sv b/wally-pipelined/testbench/testbench-busybear.sv index 920a20443..e6ba95a13 100644 --- a/wally-pipelined/testbench/testbench-busybear.sv +++ b/wally-pipelined/testbench/testbench-busybear.sv @@ -7,14 +7,9 @@ module testbench_busybear(); logic [31:0] GPIOPinsOut, GPIOPinsEn; // instantiate device to be tested - logic [`XLEN-1:0] PCF; - logic [31:0] InstrF; - logic InstrAccessFaultF, DataAccessFaultM; - logic TimerIntM = 0, SwIntM = 0; // from CLINT - logic ExtIntM = 0; // not yet connected + logic [31:0] CheckInstrF; logic [`AHBW-1:0] HRDATA; - logic HREADY, HRESP; logic [31:0] HADDR; logic [`AHBW-1:0] HWDATA; logic HWRITE; @@ -24,85 +19,116 @@ module testbench_busybear(); logic [1:0] HTRANS; logic HMASTLOCK; logic HCLK, HRESETn; + logic [`AHBW-1:0] HRDATAEXT; + logic HREADYEXT, HRESPEXT; + logic UARTSout; assign GPIOPinsIn = 0; assign UARTSin = 1; - assign HREADY = 1; - assign HRESP = 0; - assign HRDATA = 0; - // for now, seem to need these to be zero until we get a better idea - assign InstrAccessFaultF = 0; - assign DataAccessFaultM = 0; - // instantiate processor and memories - wallypipelinedhart dut(.*); + wallypipelinedsoc dut(.*); + // initialize test initial begin reset <= 1; # 22; reset <= 0; end - + // read pc trace file integer data_file_PC, scan_file_PC; initial begin - data_file_PC = $fopen("../busybear-testgen/parsedPC.txt", "r"); + data_file_PC = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r"); if (data_file_PC == 0) begin $display("file couldn't be opened"); $stop; - end + end end integer data_file_PCW, scan_file_PCW; initial begin - data_file_PCW = $fopen("../busybear-testgen/parsedPC.txt", "r"); + data_file_PCW = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r"); if (data_file_PCW == 0) begin $display("file couldn't be opened"); $stop; - end + end end // read register trace file integer data_file_rf, scan_file_rf; initial begin - data_file_rf = $fopen("../busybear-testgen/parsedRegs.txt", "r"); + data_file_rf = $fopen("/courses/e190ax/busybear_boot/parsedRegs.txt", "r"); if (data_file_rf == 0) begin $display("file couldn't be opened"); $stop; - end + end end // read CSR trace file integer data_file_csr, scan_file_csr; initial begin - data_file_csr = $fopen("../busybear-testgen/parsedCSRs.txt", "r"); + data_file_csr = $fopen("/courses/e190ax/busybear_boot/parsedCSRs.txt", "r"); if (data_file_csr == 0) begin $display("file couldn't be opened"); $stop; - end + end end // read memreads trace file integer data_file_memR, scan_file_memR; initial begin - data_file_memR = $fopen("../busybear-testgen/parsedMemRead.txt", "r"); + data_file_memR = $fopen("/courses/e190ax/busybear_boot/parsedMemRead.txt", "r"); if (data_file_memR == 0) begin $display("file couldn't be opened"); $stop; - end + end end - + // read memwrite trace file integer data_file_memW, scan_file_memW; initial begin - data_file_memW = $fopen("../busybear-testgen/parsedMemWrite.txt", "r"); + data_file_memW = $fopen("/courses/e190ax/busybear_boot/parsedMemWrite.txt", "r"); if (data_file_memW == 0) begin $display("file couldn't be opened"); $stop; - end + end end + integer warningCount = 0; + + //logic[63:0] adrTranslation[4:0]; + //string translationType[4:0] = {"rf", "writeAdr", "PCW", "PC", "readAdr"}; + //initial begin + // for(int i=0; i<5; i++) begin + // adrTranslation[i] = 64'b0; + // end + //end + + //function logic equal(logic[63:0] adr, logic[63:0] adrExpected, integer func); + // if (adr[11:0] !== adrExpected[11:0]) begin + // equal = 1'b0; + // end else begin + // equal = 1'b1; + // if ((adr+adrTranslation[func]) !== adrExpected) begin + // adrTranslation[func] = adrExpected - adr; + // $display("warning: probably new address translation %x for %s at instr %0d", adrTranslation[func], translationType[func], instrs); + // warningCount += 1; + // end + // end + //endfunction + + // pretty sure this isn't necessary anymore, but keeping this for now since its easier + function logic equal(logic[63:0] adr, logic[63:0] adrExpected, integer func); + equal = adr === adrExpected; + endfunction + + + `define ERROR \ + #10; \ + $display("processed %0d instructions with %0d warnings", instrs, warningCount); \ + $stop; + logic [63:0] pcExpected; logic [63:0] regExpected; integer regNumExpected; @@ -110,115 +136,195 @@ module testbench_busybear(); genvar i; generate for(i=1; i<32; i++) begin - always @(dut.ieu.dp.regf.rf[i]) begin - if ($time != 0) begin + always @(dut.hart.ieu.dp.regf.rf[i]) begin + if ($time == 0) begin + scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected); + if (dut.hart.ieu.dp.regf.rf[i] != regExpected) begin + $display("%0t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.hart.ieu.dp.regf.rf[i], regExpected); + `ERROR + end + end else begin scan_file_rf = $fscanf(data_file_rf, "%d\n", regNumExpected); scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected); if (i != regNumExpected) begin - $display("%t ps, instr %0d: wrong register changed: %0d, %0d expected", $time, instrs, i, regNumExpected); + $display("%0t ps, instr %0d: wrong register changed: %0d, %0d expected", $time, instrs, i, regNumExpected); + `ERROR end - if (dut.ieu.dp.regf.rf[i] != regExpected) begin - $display("%t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.ieu.dp.regf.rf[i], regExpected); + if (~equal(dut.hart.ieu.dp.regf.rf[i],regExpected, 0)) begin + $display("%0t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.hart.ieu.dp.regf.rf[i], regExpected); + `ERROR + end + if (dut.hart.ieu.dp.regf.rf[i] !== regExpected) begin + force dut.hart.ieu.dp.regf.rf[i] = regExpected; + release dut.hart.ieu.dp.regf.rf[i]; end end end end endgenerate + // RAM and bootram are addressed in 64-bit blocks - this logic handles R/W + // including subwords. Brief explanation on signals: + // + // readMask: bitmask of bits to read / write, left-shifted to align with + // nearest 64-bit boundary - examples + // HSIZE = 0 -> readMask = 11111111 + // HSIZE = 1 -> readMask = 1111111111111111 + // + // In the linux boot, the processor spends the first ~5 instructions in + // bootram, before jr jumps to main RAM + + logic [63:0] readMask; + assign readMask = ((1 << (8*(1 << HSIZE))) - 1) << 8 * HADDR[2:0]; + logic [`XLEN-1:0] readAdrExpected; - // this might need to change - always @(dut.MemRWM[1] or HADDR) begin - if (dut.MemRWM[1]) begin + + always @(dut.hart.MemRWM[1] or HADDR) begin + if (dut.hart.MemRWM[1] && HADDR != dut.PCF) begin if($feof(data_file_memR)) begin $display("no more memR data to read"); - $stop; + `ERROR end scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected); scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA); - #1; - if (HADDR != readAdrExpected) begin - $display("%t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected); + #2; + if (~equal(HADDR,readAdrExpected,4)) begin + $display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected); + `ERROR + end + + if (((readMask & HRDATA) !== (readMask & dut.HRDATA)) && (HADDR >= 'h80000000 && HADDR <= 'h87FFFFFF)) begin + $display("warning %0t ps, instr %0d: HRDATA does not equal dut.HRDATA: %x, %x from address %x, %x", $time, instrs, HRDATA, dut.HRDATA, HADDR, HSIZE); + warningCount += 1; + `ERROR end end end - + logic [`XLEN-1:0] writeDataExpected, writeAdrExpected; + // this might need to change - always @(HWDATA or HADDR or HSIZE) begin - #1; - if (HWRITE) begin + //always @(HWDATA or HADDR or HSIZE or HWRITE) begin + always @(negedge HWRITE) begin + //#1; + if ($time != 0) begin if($feof(data_file_memW)) begin $display("no more memW data to read"); - $stop; + `ERROR end scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected); scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected); if (writeDataExpected != HWDATA) begin - $display("%t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected); + $display("%0t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected); + `ERROR end - if (writeAdrExpected != HADDR) begin - $display("%t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected); + if (~equal(writeAdrExpected,HADDR,1)) begin + $display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected); + `ERROR end end end - `define CHECK_CSR(CSR) \ + integer totalCSR = 0; + logic [99:0] StartCSRexpected[63:0]; + string StartCSRname[99:0]; + initial begin + while(1) begin + scan_file_csr = $fscanf(data_file_csr, "%s\n", StartCSRname[totalCSR]); + if(StartCSRname[totalCSR] == "---") begin + break; + end + scan_file_csr = $fscanf(data_file_csr, "%x\n", StartCSRexpected[totalCSR]); + totalCSR = totalCSR + 1; + end + end + + `define CHECK_CSR2(CSR, PATH) \ string CSR; \ logic [63:0] expected``CSR``; \ //CSR checking \ - always @(dut.priv.csr.``CSR``_REGW) begin \ + always @(``PATH``.``CSR``_REGW) begin \ if ($time > 1) begin \ scan_file_csr = $fscanf(data_file_csr, "%s\n", CSR); \ scan_file_csr = $fscanf(data_file_csr, "%x\n", expected``CSR``); \ if(CSR.icompare(`"CSR`")) begin \ - $display("%t ps, instr %0d: %s changed, expected %s", $time, instrs, `"CSR`", CSR); \ + $display("%0t ps, instr %0d: %s changed, expected %s", $time, instrs, `"CSR`", CSR); \ end \ - if(dut.priv.csr.``CSR``_REGW != ``expected``CSR) begin \ - $display("%t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, CSR, CSR, dut.priv.csr.``CSR``_REGW, ``expected``CSR); \ + if(``PATH``.``CSR``_REGW != ``expected``CSR) begin \ + $display("%0t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, `"CSR`", CSR, ``PATH``.``CSR``_REGW, ``expected``CSR); \ + `ERROR \ + end \ + end else begin \ + for(integer j=0; j