Moving data memory to uncore

This commit is contained in:
David Harris 2021-01-29 15:37:51 -05:00
parent a94c09cad8
commit dc2443c55b
14 changed files with 278 additions and 258 deletions

View File

@ -57,6 +57,9 @@
// Address space
`define RESET_VECTOR 32'h80000000
// Bus Interface
`define AHBW 32
// Test modes
// Tie GPIO outputs back to inputs

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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(),

View File

@ -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

View File

@ -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