forked from Github_Repos/cvw
Moving data memory to uncore
This commit is contained in:
parent
a94c09cad8
commit
dc2443c55b
@ -57,6 +57,9 @@
|
||||
// Address space
|
||||
`define RESET_VECTOR 32'h80000000
|
||||
|
||||
// Bus Interface
|
||||
`define AHBW 32
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
188
wally-pipelined/src/subword.sv
Normal file
188
wally-pipelined/src/subword.sv
Normal 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
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user