From dc2443c55bfa753f695d04fdcc55161ce74f3558 Mon Sep 17 00:00:00 2001 From: David Harris Date: Fri, 29 Jan 2021 15:37:51 -0500 Subject: [PATCH] Moving data memory to uncore --- wally-pipelined/config/rv32ic/wally-config.vh | 3 + wally-pipelined/regression/wally-pipelined.do | 6 +- wally-pipelined/src/controller.sv | 3 +- wally-pipelined/src/datapath.sv | 8 +- wally-pipelined/src/dcu.sv | 33 ++- wally-pipelined/src/dtim.sv | 15 +- wally-pipelined/src/ieu.sv | 7 +- wally-pipelined/src/memdp.sv | 190 ------------------ wally-pipelined/src/subword.sv | 188 +++++++++++++++++ wally-pipelined/src/uart.sv | 2 +- wally-pipelined/src/{dmem.sv => uncore.sv} | 51 ++--- wally-pipelined/src/wallypipelinedhart.sv | 13 +- wally-pipelined/src/wallypipelinedsoc.sv | 5 +- .../testbench/testbench-imperas.sv | 12 +- 14 files changed, 278 insertions(+), 258 deletions(-) delete mode 100644 wally-pipelined/src/memdp.sv create mode 100644 wally-pipelined/src/subword.sv rename wally-pipelined/src/{dmem.sv => uncore.sv} (70%) diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index 7caf1a00..d59a58c9 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -57,6 +57,9 @@ // Address space `define RESET_VECTOR 32'h80000000 +// Bus Interface +`define AHBW 32 + // Test modes // Tie GPIO outputs back to inputs diff --git a/wally-pipelined/regression/wally-pipelined.do b/wally-pipelined/regression/wally-pipelined.do index 5c4715d0..a7c63cc8 100644 --- a/wally-pipelined/regression/wally-pipelined.do +++ b/wally-pipelined/regression/wally-pipelined.do @@ -63,9 +63,9 @@ add wave -divider #add wave -hex /testbench/dut/hart/ifu/PCM #add wave -hex /testbench/dut/hart/ifu/InstrM add wave /testbench/InstrMName -add wave /testbench/dut/dmem/dtim/memwrite -add wave -hex /testbench/dut/dmem/AdrM -add wave -hex /testbench/dut/dmem/WriteDataM +add wave /testbench/dut/uncore/dtim/memwrite +add wave -hex /testbench/dut/uncore/AdrM +add wave -hex /testbench/dut/uncore/WriteDataM add wave -divider add wave -hex /testbench/dut/hart/ifu/PCW add wave /testbench/InstrWName diff --git a/wally-pipelined/src/controller.sv b/wally-pipelined/src/controller.sv index 5648db2c..485f1c62 100644 --- a/wally-pipelined/src/controller.sv +++ b/wally-pipelined/src/controller.sv @@ -46,6 +46,7 @@ module controller( output logic MemReadE, // for Hazard Unit // Memory stage control signals input logic FlushM, + input logic DataMisalignedM, output logic [1:0] MemRWM, output logic CSRWriteM, PrivilegedM, output logic [2:0] Funct3M, @@ -110,7 +111,7 @@ module controller( assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD, ResultSrcD, BranchD, ALUOpD, JumpD, TargetSrcD, W64D, CSRWriteD, PrivilegedD} = ControlsD[18:1] & ~IllegalIEUInstrFaultD; - // *** move Privileged, CSRwrite + // *** move Privileged, CSRwrite?? Or move controller out of IEU into datapath and handle all instructions // ALU Decoding assign sltD = (Funct3D == 3'b010); diff --git a/wally-pipelined/src/datapath.sv b/wally-pipelined/src/datapath.sv index ef15f97e..a0afc595 100644 --- a/wally-pipelined/src/datapath.sv +++ b/wally-pipelined/src/datapath.sv @@ -45,10 +45,10 @@ module datapath ( input logic FlushM, input logic [2:0] Funct3M, input logic [`XLEN-1:0] CSRReadValM, - input logic [`XLEN-1:0] ReadDataExtM, + input logic [`XLEN-1:0] ReadDataM, input logic RetM, TrapM, output logic [`XLEN-1:0] SrcAM, - output logic [`XLEN-1:0] WriteDataFullM, DataAdrM, + output logic [`XLEN-1:0] WriteDataM, DataAdrM, // Writeback stage signals input logic FlushW, input logic RegWriteW, @@ -106,12 +106,12 @@ module datapath ( floprc #(`XLEN) SrcAMReg(clk, reset, FlushM, SrcAE, SrcAM); floprc #(`XLEN) ALUResultMReg(clk, reset, FlushM, ALUResultE, ALUResultM); assign DataAdrM = ALUResultM; - floprc #(`XLEN) WriteDataMReg(clk, reset, FlushM, WriteDataE, WriteDataFullM); + floprc #(`XLEN) WriteDataMReg(clk, reset, FlushM, WriteDataE, WriteDataM); floprc #(5) RdMEg(clk, reset, FlushM, RdE, RdM); // Writeback stage pipeline register and logic floprc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ALUResultM, ALUResultW); - floprc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ReadDataExtM, ReadDataW); + floprc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ReadDataM, ReadDataW); floprc #(`XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRValW); floprc #(5) RdWEg(clk, reset, FlushW, RdM, RdW); diff --git a/wally-pipelined/src/dcu.sv b/wally-pipelined/src/dcu.sv index c141545d..eae6224e 100644 --- a/wally-pipelined/src/dcu.sv +++ b/wally-pipelined/src/dcu.sv @@ -29,19 +29,40 @@ module dcu ( input logic [1:0] MemRWM, - input logic [`XLEN-1:0] ReadDataM, + output logic [1:0] MemRWdcuoutM, + output logic DataMisalignedM, + input logic [`XLEN-1:0] DataAdrM, input logic [2:0] Funct3M, - output logic [`XLEN-1:0] ReadDataExtM, - input logic [`XLEN-1:0] WriteDataFullM, - output logic [`XLEN-1:0] WriteDataM, - output logic [7:0] ByteMaskM, +/* output logic [`XLEN-1:0] ReadDataM, + input logic [`XLEN-1:0] WriteDataM, */ + // faults input logic DataAccessFaultM, output logic LoadMisalignedFaultM, LoadAccessFaultM, output logic StoreMisalignedFaultM, StoreAccessFaultM ); - memdp memdp(.*); +// memdp memdp(.*); + + // Determine if an Unaligned access is taking place + always_comb + case(Funct3M[1:0]) + 2'b00: DataMisalignedM = 0; // lb, sb, lbu + 2'b01: DataMisalignedM = DataAdrM[0]; // lh, sh, lhu + 2'b10: DataMisalignedM = DataAdrM[1] | DataAdrM[0]; // lw, sw, flw, fsw, lwu + 2'b11: DataMisalignedM = |DataAdrM[2:0]; // ld, sd, fld, fsd + endcase + + // Squash unaligned data accesses + // *** this is also the place to squash if the cache is hit + assign MemRWdcuoutM = MemRWM & {2{~DataMisalignedM}}; + + // Determine if address is valid + assign LoadMisalignedFaultM = DataMisalignedM & MemRWM[1]; + assign LoadAccessFaultM = DataAccessFaultM & MemRWM[0]; + assign StoreMisalignedFaultM = DataMisalignedM & MemRWM[0]; + assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0]; + endmodule diff --git a/wally-pipelined/src/dtim.sv b/wally-pipelined/src/dtim.sv index 581c3878..41cdad78 100644 --- a/wally-pipelined/src/dtim.sv +++ b/wally-pipelined/src/dtim.sv @@ -28,9 +28,9 @@ module dtim ( input logic clk, input logic [1:0] MemRWdtimM, - input logic [7:0] ByteMaskM, +// input logic [7:0] ByteMaskM, input logic [18:0] AdrM, - input logic [`XLEN-1:0] WriteDataM, + input logic [`XLEN-1:0] MaskedWriteDataM, output logic [`XLEN-1:0] RdTimM); logic [`XLEN-1:0] RAM[0:65535]; @@ -54,7 +54,7 @@ module dtim ( // UInstantiate a byte-writable memory here if possible // and drop tihs masking logic. Otherwise, use the masking // from dmem - generate + /*generate if (`XLEN==64) begin always_comb begin @@ -81,6 +81,15 @@ module dtim ( always_ff @(posedge clk) if (memwrite) RAM[AdrM[17:2]] <= write; end + endgenerate */ + generate + if (`XLEN == 64) begin + always_ff @(posedge clk) + if (memwrite) RAM[AdrM[17:3]] <= MaskedWriteDataM; + end else begin + always_ff @(posedge clk) + if (memwrite) RAM[AdrM[17:2]] <= MaskedWriteDataM; + end endgenerate endmodule diff --git a/wally-pipelined/src/ieu.sv b/wally-pipelined/src/ieu.sv index d91fd99b..80403f49 100644 --- a/wally-pipelined/src/ieu.sv +++ b/wally-pipelined/src/ieu.sv @@ -28,8 +28,9 @@ module ieu ( input logic clk, reset, output logic [1:0] MemRWM, - output logic [`XLEN-1:0] DataAdrM, WriteDataFullM, - input logic [`XLEN-1:0] ReadDataExtM, + output logic [`XLEN-1:0] DataAdrM, WriteDataM, + input logic [`XLEN-1:0] ReadDataM, + input logic DataMisalignedM, input logic DataAccessFaultM, input logic [1:0] ForwardAE, ForwardBE, input logic StallD, FlushD, FlushE, FlushM, FlushW, @@ -39,6 +40,7 @@ module ieu ( output logic RegWriteW, output logic CSRWriteM, PrivilegedM, output logic CSRWritePendingDEM, + output logic [2:0] Funct3M, output logic [`XLEN-1:0] SrcAM, output logic [`XLEN-1:0] PCTargetE, input logic [31:0] InstrD, @@ -56,7 +58,6 @@ module ieu ( logic [2:0] FlagsE; logic [4:0] ALUControlE; logic ALUSrcAE, ALUSrcBE; - logic [2:0] Funct3M; logic [1:0] ResultSrcW; logic TargetSrcE; diff --git a/wally-pipelined/src/memdp.sv b/wally-pipelined/src/memdp.sv deleted file mode 100644 index b1970d0a..00000000 --- a/wally-pipelined/src/memdp.sv +++ /dev/null @@ -1,190 +0,0 @@ -/////////////////////////////////////////// -// memdp.sv -// -// Written: David_Harris@hmc.edu 9 January 2021 -// Modified: -// -// Purpose: Memory datapath for subword accesses -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -/////////////////////////////////////////// - -`include "wally-config.vh" - -module memdp ( - input logic [1:0] MemRWM, - input logic [`XLEN-1:0] ReadDataM, - input logic [`XLEN-1:0] DataAdrM, - input logic [2:0] Funct3M, - output logic [`XLEN-1:0] ReadDataExtM, - input logic [`XLEN-1:0] WriteDataFullM, - output logic [`XLEN-1:0] WriteDataM, - output logic [7:0] ByteMaskM, - input logic DataAccessFaultM, - output logic LoadMisalignedFaultM, LoadAccessFaultM, - output logic StoreMisalignedFaultM, StoreAccessFaultM -); - - logic [7:0] bytM; - logic [15:0] HalfwordM; - logic UnalignedM; - - generate - if (`XLEN == 64) begin - // bytMe mux - always_comb - case(DataAdrM[2:0]) - 3'b000: bytM = ReadDataM[7:0]; - 3'b001: bytM = ReadDataM[15:8]; - 3'b010: bytM = ReadDataM[23:16]; - 3'b011: bytM = ReadDataM[31:24]; - 3'b100: bytM = ReadDataM[39:32]; - 3'b101: bytM = ReadDataM[47:40]; - 3'b110: bytM = ReadDataM[55:48]; - 3'b111: bytM = ReadDataM[63:56]; - endcase - - // halfword mux - always_comb - case(DataAdrM[2:1]) - 2'b00: HalfwordM = ReadDataM[15:0]; - 2'b01: HalfwordM = ReadDataM[31:16]; - 2'b10: HalfwordM = ReadDataM[47:32]; - 2'b11: HalfwordM = ReadDataM[63:48]; - endcase - - logic [31:0] word; - - always_comb - case(DataAdrM[2]) - 1'b0: word = ReadDataM[31:0]; - 1'b1: word = ReadDataM[63:32]; - endcase - - // sign extension - always_comb - case(Funct3M) - 3'b000: ReadDataExtM = {{56{bytM[7]}}, bytM}; // lb - 3'b001: ReadDataExtM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh - 3'b010: ReadDataExtM = {{32{word[31]}}, word[31:0]}; // lw - 3'b011: ReadDataExtM = ReadDataM; // ld - 3'b100: ReadDataExtM = {56'b0, bytM[7:0]}; // lbu - 3'b101: ReadDataExtM = {48'b0, HalfwordM[15:0]}; // lhu - 3'b110: ReadDataExtM = {32'b0, word[31:0]}; // lwu - default: ReadDataExtM = 64'b0; - endcase - - // Memory control - - // Compute write mask - always_comb - if (StoreMisalignedFaultM || StoreAccessFaultM) ByteMaskM = 8'b00000000; // discard Unaligned stores - else case(Funct3M) - 3'b000: begin ByteMaskM = 8'b00000000; ByteMaskM[DataAdrM[2:0]] = 1; end // sb - 3'b001: case (DataAdrM[2:1]) - 2'b00: ByteMaskM = 8'b00000011; - 2'b01: ByteMaskM = 8'b00001100; - 2'b10: ByteMaskM = 8'b00110000; - 2'b11: ByteMaskM = 8'b11000000; - endcase - 3'b010: if (DataAdrM[2]) ByteMaskM = 8'b11110000; - else ByteMaskM = 8'b00001111; - 3'b011: ByteMaskM = 8'b11111111; - default: ByteMaskM = 8'b00000000; - endcase - - // Handle subword writes - always_comb - case(Funct3M) - 3'b000: WriteDataM = {8{WriteDataFullM[7:0]}}; // sb - 3'b001: WriteDataM = {4{WriteDataFullM[15:0]}}; // sh - 3'b010: WriteDataM = {2{WriteDataFullM[31:0]}}; // sw - 3'b011: WriteDataM = WriteDataFullM; // sw - default: WriteDataM = 64'b0; - endcase - - end else begin // 32-bit - // byte mux - always_comb - case(DataAdrM[1:0]) - 2'b00: bytM = ReadDataM[7:0]; - 2'b01: bytM = ReadDataM[15:8]; - 2'b10: bytM = ReadDataM[23:16]; - 2'b11: bytM = ReadDataM[31:24]; - endcase - - // halfword mux - always_comb - case(DataAdrM[1]) - 1'b0: HalfwordM = ReadDataM[15:0]; - 1'b1: HalfwordM = ReadDataM[31:16]; - endcase - - // sign extension - always_comb - case(Funct3M) - 3'b000: ReadDataExtM = {{24{bytM[7]}}, bytM}; // lb - 3'b001: ReadDataExtM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh - 3'b010: ReadDataExtM = ReadDataM; // lw - 3'b100: ReadDataExtM = {24'b0, bytM[7:0]}; // lbu - 3'b101: ReadDataExtM = {16'b0, HalfwordM[15:0]}; // lhu - default: ReadDataExtM = 32'b0; - endcase - - // Memory control - - // Compute write mask - always_comb - if (StoreMisalignedFaultM || StoreAccessFaultM) ByteMaskM = 8'b0000; // discard Unaligned stores - else case(Funct3M) - 3'b000: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0,DataAdrM[1:0]}] = 1; end // sb - 3'b001: if (DataAdrM[1]) ByteMaskM = 8'b1100; - else ByteMaskM = 8'b0011; - 3'b010: ByteMaskM = 8'b1111; - default: ByteMaskM = 8'b0000; - endcase - - // Handle subword writes - always_comb - case(Funct3M) - 3'b000: WriteDataM = {4{WriteDataFullM[7:0]}}; // sb - 3'b001: WriteDataM = {2{WriteDataFullM[15:0]}}; // sh - 3'b010: WriteDataM = WriteDataFullM; // sw - default: WriteDataM = 32'b0; - endcase - end - endgenerate - - // Determine if an Unaligned access is taking place - always_comb - case(Funct3M) - 3'b000: UnalignedM = 0; // lb, sb - 3'b001: UnalignedM = DataAdrM[0]; // lh, sh - 3'b010: UnalignedM = DataAdrM[1] | DataAdrM[0]; // lw, sw, flw, fsw - 3'b011: UnalignedM = |DataAdrM[2:0]; // ld, sd, fld, fsd - 3'b100: UnalignedM = 0; // lbu - 3'b101: UnalignedM = DataAdrM[0]; // lhu - 3'b110: UnalignedM = |DataAdrM[1:0]; // lwu - default: UnalignedM = 0; - endcase - - // Determine if address is valid - assign LoadMisalignedFaultM = UnalignedM & MemRWM[1]; - assign LoadAccessFaultM = DataAccessFaultM & MemRWM[0]; - assign StoreMisalignedFaultM = UnalignedM & MemRWM[0]; - assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0]; -endmodule diff --git a/wally-pipelined/src/subword.sv b/wally-pipelined/src/subword.sv new file mode 100644 index 00000000..6b9a544a --- /dev/null +++ b/wally-pipelined/src/subword.sv @@ -0,0 +1,188 @@ +/////////////////////////////////////////// +// subword.sv +// +// Written: David_Harris@hmc.edu 9 January 2021 +// Modified: +// +// Purpose: Masking and muxing for subword accesses +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +`include "wally-config.vh" + +module subword ( + input logic [1:0] MemRWM, + input logic [`XLEN-1:0] ReadDataUnmaskedM, + input logic [`XLEN-1:0] AdrM, + input logic [2:0] Funct3M, + output logic [`XLEN-1:0] ReadDataM, + input logic [`XLEN-1:0] WriteDataM, + output logic [`XLEN-1:0] MaskedWriteDataM +); + + logic [7:0] ByteM; // *** declare locally to generate as either 4 or 8 bits + logic [15:0] HalfwordM; + logic [`XLEN-1:0] WriteDataSubwordDuplicated; + logic [7:0] ByteMaskM; + + generate + if (`XLEN == 64) begin + // ByteMe mux + always_comb + case(AdrM[2:0]) + 3'b000: ByteM = ReadDataUnmaskedM[7:0]; + 3'b001: ByteM = ReadDataUnmaskedM[15:8]; + 3'b010: ByteM = ReadDataUnmaskedM[23:16]; + 3'b011: ByteM = ReadDataUnmaskedM[31:24]; + 3'b100: ByteM = ReadDataUnmaskedM[39:32]; + 3'b101: ByteM = ReadDataUnmaskedM[47:40]; + 3'b110: ByteM = ReadDataUnmaskedM[55:48]; + 3'b111: ByteM = ReadDataUnmaskedM[63:56]; + endcase + + // halfword mux + always_comb + case(AdrM[2:1]) + 2'b00: HalfwordM = ReadDataUnmaskedM[15:0]; + 2'b01: HalfwordM = ReadDataUnmaskedM[31:16]; + 2'b10: HalfwordM = ReadDataUnmaskedM[47:32]; + 2'b11: HalfwordM = ReadDataUnmaskedM[63:48]; + endcase + + logic [31:0] WordM; + + always_comb + case(AdrM[2]) + 1'b0: WordM = ReadDataUnmaskedM[31:0]; + 1'b1: WordM = ReadDataUnmaskedM[63:32]; + endcase + + // sign extension + always_comb + case(Funct3M) + 3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb + 3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh + 3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw + 3'b011: ReadDataM = ReadDataUnmaskedM; // ld + 3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu + 3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu + 3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu + default: ReadDataM = 64'b0; + endcase + + // Memory control + + // Compute write mask + always_comb + case(Funct3M) + 3'b000: begin ByteMaskM = 8'b00000000; ByteMaskM[AdrM[2:0]] = 1; end // sb + 3'b001: case (AdrM[2:1]) + 2'b00: ByteMaskM = 8'b00000011; + 2'b01: ByteMaskM = 8'b00001100; + 2'b10: ByteMaskM = 8'b00110000; + 2'b11: ByteMaskM = 8'b11000000; + endcase + 3'b010: if (AdrM[2]) ByteMaskM = 8'b11110000; + else ByteMaskM = 8'b00001111; + 3'b011: ByteMaskM = 8'b11111111; + default: ByteMaskM = 8'b00000000; + endcase + + // Handle subword writes + always_comb + case(Funct3M) + 3'b000: WriteDataSubwordDuplicated = {8{WriteDataM[7:0]}}; // sb + 3'b001: WriteDataSubwordDuplicated = {4{WriteDataM[15:0]}}; // sh + 3'b010: WriteDataSubwordDuplicated = {2{WriteDataM[31:0]}}; // sw + 3'b011: WriteDataSubwordDuplicated = WriteDataM; // sw + default: WriteDataSubwordDuplicated = 64'b0; + endcase + + always_comb begin + MaskedWriteDataM=ReadDataUnmaskedM; + if (ByteMaskM[0]) MaskedWriteDataM[7:0] = WriteDataSubwordDuplicated[7:0]; + if (ByteMaskM[1]) MaskedWriteDataM[15:8] = WriteDataSubwordDuplicated[15:8]; + if (ByteMaskM[2]) MaskedWriteDataM[23:16] = WriteDataSubwordDuplicated[23:16]; + if (ByteMaskM[3]) MaskedWriteDataM[31:24] = WriteDataSubwordDuplicated[31:24]; + if (ByteMaskM[4]) MaskedWriteDataM[39:32] = WriteDataSubwordDuplicated[39:32]; + if (ByteMaskM[5]) MaskedWriteDataM[47:40] = WriteDataSubwordDuplicated[47:40]; + if (ByteMaskM[6]) MaskedWriteDataM[55:48] = WriteDataSubwordDuplicated[55:48]; + if (ByteMaskM[7]) MaskedWriteDataM[63:56] = WriteDataSubwordDuplicated[63:56]; + end + + end else begin // 32-bit + // byte mux + always_comb + case(AdrM[1:0]) + 2'b00: ByteM = ReadDataUnmaskedM[7:0]; + 2'b01: ByteM = ReadDataUnmaskedM[15:8]; + 2'b10: ByteM = ReadDataUnmaskedM[23:16]; + 2'b11: ByteM = ReadDataUnmaskedM[31:24]; + endcase + + // halfword mux + always_comb + case(AdrM[1]) + 1'b0: HalfwordM = ReadDataUnmaskedM[15:0]; + 1'b1: HalfwordM = ReadDataUnmaskedM[31:16]; + endcase + + // sign extension + always_comb + case(Funct3M) + 3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb + 3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh + 3'b010: ReadDataM = ReadDataUnmaskedM; // lw + 3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu + 3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu + default: ReadDataM = 32'b0; + endcase + + // Memory control + + // Compute write mask + always_comb + case(Funct3M) + 3'b000: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0, AdrM[1:0]}] = 1; end // sb + 3'b001: if (AdrM[1]) ByteMaskM = 8'b1100; + else ByteMaskM = 8'b0011; + 3'b010: ByteMaskM = 8'b1111; + default: ByteMaskM = 8'b0000; + endcase + + // Handle subword writes + always_comb + case(Funct3M) + 3'b000: WriteDataSubwordDuplicated = {4{WriteDataM[7:0]}}; // sb + 3'b001: WriteDataSubwordDuplicated = {2{WriteDataM[15:0]}}; // sh + 3'b010: WriteDataSubwordDuplicated = WriteDataM; // sw + default: WriteDataSubwordDuplicated = 32'b0; + endcase + + always_comb begin + MaskedWriteDataM=ReadDataUnmaskedM; + if (ByteMaskM[0]) MaskedWriteDataM[7:0] = WriteDataSubwordDuplicated[7:0]; + if (ByteMaskM[1]) MaskedWriteDataM[15:8] = WriteDataSubwordDuplicated[15:8]; + if (ByteMaskM[2]) MaskedWriteDataM[23:16] = WriteDataSubwordDuplicated[23:16]; + if (ByteMaskM[3]) MaskedWriteDataM[31:24] = WriteDataSubwordDuplicated[31:24]; + end + + end + endgenerate + +endmodule diff --git a/wally-pipelined/src/uart.sv b/wally-pipelined/src/uart.sv index 04e787d7..2d792834 100644 --- a/wally-pipelined/src/uart.sv +++ b/wally-pipelined/src/uart.sv @@ -30,7 +30,7 @@ module uart ( input logic clk, reset, input logic [1:0] MemRWuartM, - input logic [7:0] ByteMaskM, +// input logic [7:0] ByteMaskM, input logic [`XLEN-1:0] AdrM, input logic [`XLEN-1:0] MaskedWriteDataM, output logic [`XLEN-1:0] RdUARTM, diff --git a/wally-pipelined/src/dmem.sv b/wally-pipelined/src/uncore.sv similarity index 70% rename from wally-pipelined/src/dmem.sv rename to wally-pipelined/src/uncore.sv index fcd1f2de..a4b9be36 100644 --- a/wally-pipelined/src/dmem.sv +++ b/wally-pipelined/src/uncore.sv @@ -1,10 +1,11 @@ /////////////////////////////////////////// -// dmem.sv +// uncore.sv // // Written: David_Harris@hmc.edu 9 January 2021 // Modified: // -// Purpose: Data memory +// Purpose: System-on-Chip components outside the core (hart) +// Memories, peripherals, external bus control // // A component of the Wally configurable RISC-V project. // @@ -27,26 +28,31 @@ // *** need idiom to map onto cache RAM with byte writes // *** and use memread signal to reduce power when reads aren't needed -module dmem ( +module uncore ( input logic clk, reset, + // bus interface input logic [1:0] MemRWM, - input logic [7:0] ByteMaskM, input logic [`XLEN-1:0] AdrM, WriteDataM, + input logic [2:0] Funct3M, output logic [`XLEN-1:0] ReadDataM, output logic DataAccessFaultM, + // peripheral pins output logic TimerIntM, SwIntM, input logic [31:0] GPIOPinsIn, output logic [31:0] GPIOPinsOut, GPIOPinsEn, input logic UARTSin, - output logic UARTSout); + output logic UARTSout + ); logic [`XLEN-1:0] MaskedWriteDataM; + logic [`XLEN-1:0] ReadDataUnmaskedM; logic [`XLEN-1:0] RdTimM, RdCLINTM, RdGPIOM, RdUARTM; logic TimEnM, CLINTEnM, GPIOEnM, UARTEnM; logic [1:0] MemRWdtimM, MemRWclintM, MemRWgpioM, MemRWuartM; logic UARTIntr;// *** will need to tie INTR to an interrupt handler // Address decoding + // *** generalize, use configurable generate if (`XLEN == 64) assign TimEnM = ~(|AdrM[`XLEN-1:32]) & AdrM[31] & ~(|AdrM[30:19]); // 0x000...80000000 - 0x000...8007FFFF @@ -57,6 +63,7 @@ module dmem ( assign GPIOEnM = (AdrM[31:8] == 24'h10012); // 0x10012000-0x100120FF assign UARTEnM = ~(|AdrM[`XLEN-1:29]) & AdrM[28] & ~(|AdrM[27:3]); // 0x10000000-0x10000007 + // Enable read or write based on decoded address. assign MemRWdtimM = MemRWM & {2{TimEnM}}; assign MemRWclintM = MemRWM & {2{CLINTEnM}}; assign MemRWgpioM = MemRWM & {2{GPIOEnM}}; @@ -72,37 +79,15 @@ module dmem ( .DSRb(1'b1), .DCDb(1'b1), .CTSb(1'b0), .RIb(1'b1), .RTSb(), .DTRb(), .OUT1b(), .OUT2b(), .*); - // *** add cache and interface to external memory & other peripherals + // *** Interface to off-chip memory would appear as another peripheral // merge reads - assign ReadDataM = ({`XLEN{TimEnM}} & RdTimM) | ({`XLEN{CLINTEnM}} & RdCLINTM) | + assign ReadDataUnmaskedM = ({`XLEN{TimEnM}} & RdTimM) | ({`XLEN{CLINTEnM}} & RdCLINTM) | ({`XLEN{GPIOEnM}} & RdGPIOM) | ({`XLEN{UARTEnM}} & RdUARTM); - assign DataAccessFaultM = ~(|TimEnM | CLINTEnM | GPIOEnM | UARTEnM); - - // byte masking - // write each byte based on the byte mask - generate - if (`XLEN==64) begin - always_comb begin - MaskedWriteDataM=ReadDataM; - if (ByteMaskM[0]) MaskedWriteDataM[7:0] = WriteDataM[7:0]; - if (ByteMaskM[1]) MaskedWriteDataM[15:8] = WriteDataM[15:8]; - if (ByteMaskM[2]) MaskedWriteDataM[23:16] = WriteDataM[23:16]; - if (ByteMaskM[3]) MaskedWriteDataM[31:24] = WriteDataM[31:24]; - if (ByteMaskM[4]) MaskedWriteDataM[39:32] = WriteDataM[39:32]; - if (ByteMaskM[5]) MaskedWriteDataM[47:40] = WriteDataM[47:40]; - if (ByteMaskM[6]) MaskedWriteDataM[55:48] = WriteDataM[55:48]; - if (ByteMaskM[7]) MaskedWriteDataM[63:56] = WriteDataM[63:56]; - end - end else begin // 32-bit - always_comb begin - if (ByteMaskM[0]) MaskedWriteDataM[7:0] = WriteDataM[7:0]; - if (ByteMaskM[1]) MaskedWriteDataM[15:8] = WriteDataM[15:8]; - if (ByteMaskM[2]) MaskedWriteDataM[23:16] = WriteDataM[23:16]; - if (ByteMaskM[3]) MaskedWriteDataM[31:24] = WriteDataM[31:24]; - end - end - endgenerate + assign DataAccessFaultM = ~(TimEnM | CLINTEnM | GPIOEnM | UARTEnM); + // subword accesses: converts ReadDataUnmaskedM to ReadDataM and WriteDataM to MaskedWriteDataM + subword subword(.*); + endmodule diff --git a/wally-pipelined/src/wallypipelinedhart.sv b/wally-pipelined/src/wallypipelinedhart.sv index 586daf7d..4a9551b2 100644 --- a/wally-pipelined/src/wallypipelinedhart.sv +++ b/wally-pipelined/src/wallypipelinedhart.sv @@ -30,10 +30,10 @@ module wallypipelinedhart ( input logic clk, reset, output logic [`XLEN-1:0] PCF, input logic [31:0] InstrF, - output logic [1:0] MemRWM, - output logic [7:0] ByteMaskM, - output logic [`XLEN-1:0] DataAdrM, WriteDataM, - input logic [`XLEN-1:0] ReadDataM, + output logic [1:0] MemRWdcuoutM, // *** should be removed when EBU enabled + output logic [2:0] Funct3M, // *** remove when EBU enabled + output logic [`XLEN-1:0] DataAdrM, WriteDataM, // *** + input logic [`XLEN-1:0] ReadDataM, // *** input logic TimerIntM, ExtIntM, SwIntM, input logic InstrAccessFaultF, input logic DataAccessFaultM, @@ -62,9 +62,10 @@ module wallypipelinedhart ( logic [`XLEN-1:0] PCTargetE; logic [`XLEN-1:0] CSRReadValM; logic [`XLEN-1:0] PrivilegedNextPCM; - logic [`XLEN-1:0] ReadDataExtM, WriteDataFullM; + logic [1:0] MemRWM; logic InstrValidW; logic InstrMisalignedFaultM; + logic DataMisalignedM; logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD; logic LoadMisalignedFaultM, LoadAccessFaultM; logic StoreMisalignedFaultM, StoreAccessFaultM; @@ -86,7 +87,7 @@ module wallypipelinedhart ( ifu ifu(.*); // instruction fetch unit: PC, branch prediction, instruction cache ieu ieu(.*); // inteber execution unit: integer register file, datapath and controller - dcu dcu(.Funct3M(InstrM[14:12]), .*); // data cache unit + dcu dcu(/*.Funct3M(InstrM[14:12]),*/ .*); // data cache unit ahblite ebu( .IPAdrD(zero), .IReadD(1'b0), .IRData(), .IReady(), diff --git a/wally-pipelined/src/wallypipelinedsoc.sv b/wally-pipelined/src/wallypipelinedsoc.sv index 40d7dd4d..bd190765 100644 --- a/wally-pipelined/src/wallypipelinedsoc.sv +++ b/wally-pipelined/src/wallypipelinedsoc.sv @@ -55,7 +55,8 @@ module wallypipelinedsoc ( logic [`XLEN-1:0] DataAdrM, WriteDataM; logic [`XLEN-1:0] PCF, ReadDataM; logic [31:0] InstrF; - logic [7:0] ByteMaskM; + logic [2:0] Funct3M; + logic [1:0] MemRWdcuoutM; logic InstrAccessFaultF, DataAccessFaultM; logic TimerIntM, SwIntM; // from CLINT logic ExtIntM = 0; // not yet connected @@ -64,5 +65,5 @@ module wallypipelinedsoc ( wallypipelinedhart hart(.*); imem imem(.AdrF(PCF[`XLEN-1:1]), .*); - dmem dmem(.AdrM(DataAdrM), .*); + uncore uncore(.AdrM(DataAdrM), .MemRWM(MemRWdcuoutM), .*); endmodule \ No newline at end of file diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 78c205d2..7d73be97 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -263,7 +263,7 @@ string tests32i[] = { dut.hart.ifu.InstrM, InstrW, InstrDName, InstrEName, InstrMName, InstrWName); - // initialize test + // initialize tests initial begin test = 0; @@ -274,12 +274,12 @@ string tests32i[] = { else meminit = 64'hFEDCBA9876543210; for (i=0; i<=65535; i = i+1) begin //dut.imem.RAM[i] = meminit; - // dut.dmem.RAM[i] = meminit; + // dut.uncore.RAM[i] = meminit; end // read test vectors into memory memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; $readmemh(memfilename, dut.imem.RAM); - $readmemh(memfilename, dut.dmem.dtim.RAM); + $readmemh(memfilename, dut.uncore.dtim.RAM); reset = 1; # 22; reset = 0; end @@ -325,13 +325,13 @@ string tests32i[] = { /* verilator lint_off INFINITELOOP */ while (signature[i] !== 'bx) begin //$display("signature[%h] = %h", i, signature[i]); - if (signature[i] !== dut.dmem.dtim.RAM[testadr+i]) begin + if (signature[i] !== dut.uncore.dtim.RAM[testadr+i]) begin if (signature[i+4] !== 'bx || signature[i] !== 32'hFFFFFFFF) begin // report errors unless they are garbage at the end of the sim // kind of hacky test for garbage right now errors = errors+1; $display(" Error on test %s result %d: adr = %h sim = %h, signature = %h", - tests[test], i, (testadr+i)*`XLEN/8, dut.dmem.dtim.RAM[testadr+i], signature[i]); + tests[test], i, (testadr+i)*`XLEN/8, dut.uncore.dtim.RAM[testadr+i], signature[i]); end end i = i + 1; @@ -351,7 +351,7 @@ string tests32i[] = { else begin memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; $readmemh(memfilename, dut.imem.RAM); - $readmemh(memfilename, dut.dmem.dtim.RAM); + $readmemh(memfilename, dut.uncore.dtim.RAM); $display("Read memfile %s", memfilename); reset = 1; # 17; reset = 0; end