mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
More memory interface, ALU testgen
This commit is contained in:
parent
b121b90b28
commit
cc42655789
@ -38,9 +38,8 @@ module ahblite (
|
|||||||
// Signals from Instruction Cache
|
// Signals from Instruction Cache
|
||||||
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
|
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
|
||||||
input logic InstrReadF,
|
input logic InstrReadF,
|
||||||
input logic ResolveBranchD,
|
// input logic ResolveBranchD,
|
||||||
output logic [31:0] InstrRData,
|
output logic [31:0] InstrRData,
|
||||||
// output logic IReady,
|
|
||||||
// Signals from Data Cache
|
// Signals from Data Cache
|
||||||
input logic [`XLEN-1:0] MemPAdrM,
|
input logic [`XLEN-1:0] MemPAdrM,
|
||||||
input logic MemReadM, MemWriteM,
|
input logic MemReadM, MemWriteM,
|
||||||
@ -48,7 +47,6 @@ module ahblite (
|
|||||||
input logic [1:0] MemSizeM,
|
input logic [1:0] MemSizeM,
|
||||||
// Return from bus
|
// Return from bus
|
||||||
output logic [`XLEN-1:0] ReadDataW,
|
output logic [`XLEN-1:0] ReadDataW,
|
||||||
// output logic DReady,
|
|
||||||
// AHB-Lite external signals
|
// AHB-Lite external signals
|
||||||
input logic [`AHBW-1:0] HRDATA,
|
input logic [`AHBW-1:0] HRDATA,
|
||||||
input logic HREADY, HRESP,
|
input logic HREADY, HRESP,
|
||||||
@ -61,14 +59,12 @@ module ahblite (
|
|||||||
output logic [3:0] HPROT,
|
output logic [3:0] HPROT,
|
||||||
output logic [1:0] HTRANS,
|
output logic [1:0] HTRANS,
|
||||||
output logic HMASTLOCK,
|
output logic HMASTLOCK,
|
||||||
// Delayed signals for subword write
|
// Delayed signals for writes
|
||||||
output logic [2:0] HADDRD,
|
output logic [2:0] HADDRD,
|
||||||
output logic [3:0] HSIZED,
|
output logic [3:0] HSIZED,
|
||||||
output logic HWRITED,
|
output logic HWRITED,
|
||||||
// Acknowledge
|
|
||||||
output logic InstrAckD, MemAckW,
|
|
||||||
// Stalls
|
// Stalls
|
||||||
output logic InstrStall, DataStall
|
output logic InstrStall,/*InstrUpdate, */DataStall
|
||||||
);
|
);
|
||||||
|
|
||||||
logic GrantData;
|
logic GrantData;
|
||||||
@ -81,12 +77,61 @@ module ahblite (
|
|||||||
assign HCLK = clk;
|
assign HCLK = clk;
|
||||||
assign HRESETn = ~reset;
|
assign HRESETn = ~reset;
|
||||||
|
|
||||||
// Arbitrate requests by giving data priority over instructions
|
|
||||||
assign GrantData = MemReadM | MemWriteM;
|
|
||||||
|
|
||||||
// *** initially support HABW = XLEN
|
// *** initially support HABW = XLEN
|
||||||
|
|
||||||
// track bus state
|
// track bus state
|
||||||
|
// Data accesses have priority over instructions. However, if a data access comes
|
||||||
|
// while an instruction read is occuring, the instruction read finishes before
|
||||||
|
// the data access can take place.
|
||||||
|
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADMEMPENDING} statetype;
|
||||||
|
statetype BusState, NextBusState;
|
||||||
|
|
||||||
|
always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
|
if (~HRESETn) BusState <= #1 IDLE;
|
||||||
|
else BusState <= #1 NextBusState;
|
||||||
|
|
||||||
|
always_comb
|
||||||
|
case (BusState)
|
||||||
|
IDLE: if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions
|
||||||
|
else if (MemWriteM) NextBusState = MEMWRITE;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
INSTRREAD: //if (~HREADY & (MemReadM | MemWriteM)) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
|
||||||
|
if (~HREADY) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
INSTRREADMEMPENDING: if (~HREADY) NextBusState = INSTRREADMEMPENDING; // *** shouldn't happen, delete
|
||||||
|
else if (MemReadM) NextBusState = MEMREAD;
|
||||||
|
else NextBusState = MEMWRITE; // must be write if not a read. Don't return to idle.
|
||||||
|
endcase
|
||||||
|
|
||||||
|
// stall signals
|
||||||
|
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || (NextBusState == INSTRREADMEMPENDING);
|
||||||
|
assign #1 InstrStall = (NextBusState == INSTRREAD);
|
||||||
|
// assign InstrUpdate = (BusState == INSTRREADMEMPENDING) && (NextBusState != INSTRREADMEMPENDING);
|
||||||
|
|
||||||
|
// bus outputs
|
||||||
|
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE);
|
||||||
|
assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
||||||
|
assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize;
|
||||||
|
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
|
||||||
|
assign HPROT = 4'b0011; // not used; see Section 3.7
|
||||||
|
assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
|
||||||
|
assign HMASTLOCK = 0; // no locking supported
|
||||||
|
assign HWRITE = (NextBusState == MEMWRITE);
|
||||||
|
// delay write data by one cycle for
|
||||||
|
flop #(`XLEN) wdreg(HCLK, WriteDataM, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
|
||||||
|
// delay signals for subword writes
|
||||||
|
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
|
||||||
|
flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED);
|
||||||
|
flop #(1) writereg(HCLK, HWRITE, HWRITED);
|
||||||
|
|
||||||
|
/*
|
||||||
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD} statetype;
|
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD} statetype;
|
||||||
statetype AdrState, DataState, NextAdrState; // what is happening in the first and second phases of the bus
|
statetype AdrState, DataState, NextAdrState; // what is happening in the first and second phases of the bus
|
||||||
always_ff @(posedge HCLK, negedge HRESETn)
|
always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
@ -117,13 +162,42 @@ module ahblite (
|
|||||||
assign MemAckW = (AdrState == MEMREAD || AdrState == MEMWRITE) && HREADY;
|
assign MemAckW = (AdrState == MEMREAD || AdrState == MEMWRITE) && HREADY;
|
||||||
assign InstrAckD = (AdrState == INSTRREAD) && HREADY;
|
assign InstrAckD = (AdrState == INSTRREAD) && HREADY;
|
||||||
|
|
||||||
|
// State machines for stalls (probably can merge with FSM above***)
|
||||||
|
// Idle, DataBusy, InstrBusy. Stall while in busystate add suffixes
|
||||||
|
logic MemState, NextMemState, InstrState, NextInstrState;
|
||||||
|
flopr #(1) msreg(HCLK, ~HRESETn, NextMemState, MemState);
|
||||||
|
flopr #(1) isreg(HCLK, ~HRESETn, NextInstrState, InstrState);
|
||||||
|
/* always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
|
if (~HRESETn) MemState <= 0;
|
||||||
|
else MemState <= NextMemState;
|
||||||
|
assign NextMemState = (MemState == 0 && InstrState == 0 && (MemReadM || MemWriteM)) || (MemState == 1 && ~MemAckW);
|
||||||
|
assign DataStall = NextMemState;
|
||||||
|
/* always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
|
if (~HRESETn) InstrState <= 0;
|
||||||
|
else InstrState <= NextInstrState;
|
||||||
|
|
||||||
|
assign NextInstrState = (InstrState == 0 && MemState == 0 && (~MemReadM && ~MemWriteM && InstrReadF)) ||
|
||||||
|
(InstrState == 1 && ~InstrAckD) ||
|
||||||
|
(InstrState == 1 && ResolveBranchD); // dh 2/8/2021 fixing; delete this later
|
||||||
|
/* assign NextInstrState = (InstrState == 0 && MemState == 0 && (~MemReadM && ~MemWriteM)) ||
|
||||||
|
(InstrState == 1 && ~InstrAckD); // *** removed InstrReadF above dh 2/9/20
|
||||||
|
assign InstrStall = NextInstrState | MemState | NextMemState; // *** check this, explain better
|
||||||
|
// temporarily turn off stalls and check it works
|
||||||
|
//assign DataStall = 0;
|
||||||
|
//assign InstrStall = 0;
|
||||||
|
|
||||||
|
assign DReady = HREADY & GrantData; // ***unused?
|
||||||
|
assign IReady = HREADY & InstrReadF & ~GrantData; // maybe unused?***
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// Choose ISize based on XLen
|
// Choose ISize based on XLen
|
||||||
generate
|
generate
|
||||||
//if (`AHBW == 32) assign ISize = 3'b010; // 32-bit transfers
|
//if (`AHBW == 32) assign ISize = 3'b010; // 32-bit transfers
|
||||||
//else assign ISize = 3'b011; // 64-bit transfers
|
//else assign ISize = 3'b011; // 64-bit transfers
|
||||||
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width
|
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width
|
||||||
endgenerate
|
endgenerate
|
||||||
|
/*
|
||||||
// drive bus outputs
|
// drive bus outputs
|
||||||
assign HADDR = GrantData ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
assign HADDR = GrantData ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
||||||
//assign HWDATA = WriteDataW;
|
//assign HWDATA = WriteDataW;
|
||||||
@ -134,41 +208,16 @@ module ahblite (
|
|||||||
assign HPROT = 4'b0011; // not used; see Section 3.7
|
assign HPROT = 4'b0011; // not used; see Section 3.7
|
||||||
assign HTRANS = InstrReadF | MemReadM | MemWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
|
assign HTRANS = InstrReadF | MemReadM | MemWriteM ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
|
||||||
assign HMASTLOCK = 0; // no locking supported
|
assign HMASTLOCK = 0; // no locking supported
|
||||||
|
*/
|
||||||
// Route signals to Instruction and Data Caches
|
// Route signals to Instruction and Data Caches
|
||||||
// *** assumes AHBW = XLEN
|
// *** assumes AHBW = XLEN
|
||||||
assign InstrRData = HRDATAMasked[31:0];
|
assign InstrRData = HRDATAMasked[31:0];
|
||||||
assign IReady = HREADY & InstrReadF & ~GrantData; // maybe unused?***
|
|
||||||
// assign ReadDataW = HRDATAMasked;
|
// assign ReadDataW = HRDATAMasked;
|
||||||
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
|
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
|
||||||
flopenrc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ~StallW, ReadDataM, ReadDataW);
|
assign CaptureDataM = (BusState == MEMREAD) && (NextBusState != MEMREAD);
|
||||||
assign DReady = HREADY & GrantData; // ***unused?
|
flopenr #(`XLEN) ReadDataWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataW);
|
||||||
|
|
||||||
|
|
||||||
// State machines for stalls (probably can merge with FSM above***)
|
|
||||||
// Idle, DataBusy, InstrBusy. Stall while in busystate add suffixes
|
|
||||||
logic MemState, NextMemState, InstrState, NextInstrState;
|
|
||||||
flopr #(1) msreg(HCLK, ~HRESETn, NextMemState, MemState);
|
|
||||||
flopr #(1) isreg(HCLK, ~HRESETn, NextInstrState, InstrState);
|
|
||||||
/* always_ff @(posedge HCLK, negedge HRESETn)
|
|
||||||
if (~HRESETn) MemState <= 0;
|
|
||||||
else MemState <= NextMemState; */
|
|
||||||
assign NextMemState = (MemState == 0 && InstrState == 0 && (MemReadM || MemWriteM)) || (MemState == 1 && ~MemAckW);
|
|
||||||
assign DataStall = NextMemState;
|
|
||||||
/* always_ff @(posedge HCLK, negedge HRESETn)
|
|
||||||
if (~HRESETn) InstrState <= 0;
|
|
||||||
else InstrState <= NextInstrState;*/
|
|
||||||
|
|
||||||
assign NextInstrState = (InstrState == 0 && MemState == 0 && (~MemReadM && ~MemWriteM && InstrReadF)) ||
|
|
||||||
(InstrState == 1 && ~InstrAckD) ||
|
|
||||||
(InstrState == 1 && ResolveBranchD); // dh 2/8/2021 fixing; delete this later
|
|
||||||
/* assign NextInstrState = (InstrState == 0 && MemState == 0 && (~MemReadM && ~MemWriteM)) ||
|
|
||||||
(InstrState == 1 && ~InstrAckD); // *** removed InstrReadF above dh 2/9/20 */
|
|
||||||
assign InstrStall = NextInstrState | MemState | NextMemState; // *** check this, explain better
|
|
||||||
// temporarily turn off stalls and check it works
|
|
||||||
//assign DataStall = 0;
|
|
||||||
//assign InstrStall = 0;
|
|
||||||
|
|
||||||
// stalls
|
// stalls
|
||||||
// Stall MEM stage if data is being accessed and bus isn't yet ready
|
// Stall MEM stage if data is being accessed and bus isn't yet ready
|
||||||
//assign DataStall = GrantData & ~HREADY;
|
//assign DataStall = GrantData & ~HREADY;
|
||||||
|
@ -47,6 +47,16 @@ module flopr #(parameter WIDTH = 8) (
|
|||||||
else q <= #1 d;
|
else q <= #1 d;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// flop with enable
|
||||||
|
module flopen #(parameter WIDTH = 8) (
|
||||||
|
input logic clk, en,
|
||||||
|
input logic [WIDTH-1:0] d,
|
||||||
|
output logic [WIDTH-1:0] q);
|
||||||
|
|
||||||
|
always_ff @(posedge clk)
|
||||||
|
if (en) q <= #1 d;
|
||||||
|
endmodule
|
||||||
|
|
||||||
// flop with enable, asynchronous reset, synchronous clear
|
// flop with enable, asynchronous reset, synchronous clear
|
||||||
module flopenrc #(parameter WIDTH = 8) (
|
module flopenrc #(parameter WIDTH = 8) (
|
||||||
input logic clk, reset, clear, en,
|
input logic clk, reset, clear, en,
|
||||||
|
@ -56,12 +56,12 @@ module hazard(
|
|||||||
|
|
||||||
assign BranchFlushDE = PCSrcE | RetM | TrapM;
|
assign BranchFlushDE = PCSrcE | RetM | TrapM;
|
||||||
|
|
||||||
assign StallFCause = InstrStall | CSRWritePendingDEM; // stall at fetch if unable to get the instruction,
|
assign StallFCause = /*InstrStall | */ CSRWritePendingDEM; // stall at fetch if unable to get the instruction,
|
||||||
// or if a CSR will be written and may change system behavior
|
// or if a CSR will be written and may change system behavior
|
||||||
assign StallDCause = LoadStallD; // stall in decode if instruction is a load dependent on previous
|
assign StallDCause = LoadStallD; // stall in decode if instruction is a load dependent on previous
|
||||||
assign StallECause = 0;
|
assign StallECause = 0;
|
||||||
assign StallMCause = 0; // sDataStall; // not yet used***
|
assign StallMCause = 0; // sDataStall; // not yet used***
|
||||||
assign StallWCause = DataStall; // | InstrStall;
|
assign StallWCause = DataStall | InstrStall;
|
||||||
|
|
||||||
// Each stage stalls if the next stage is stalled or there is a cause to stall this stage.
|
// Each stage stalls if the next stage is stalled or there is a cause to stall this stage.
|
||||||
assign StallF = StallD | StallFCause;
|
assign StallF = StallD | StallFCause;
|
||||||
|
@ -67,18 +67,20 @@ module ifu (
|
|||||||
|
|
||||||
// *** put memory interface on here, InstrF becomes output
|
// *** put memory interface on here, InstrF becomes output
|
||||||
assign InstrPAdrF = PCF; // *** no MMU
|
assign InstrPAdrF = PCF; // *** no MMU
|
||||||
assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
|
//assign InstrReadF = ~StallD; // *** & ICacheMissF; add later
|
||||||
|
assign InstrReadF = 1; // *** & ICacheMissF; add later
|
||||||
|
|
||||||
assign PrivilegedChangePCM = RetM | TrapM;
|
assign PrivilegedChangePCM = RetM | TrapM;
|
||||||
|
|
||||||
assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
|
//assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
|
||||||
|
|
||||||
// dh 2/8/2022 keep in instruction fetch stall mode when taking branch
|
// dh 2/8/2022 keep in instruction fetch stall mode when taking branch
|
||||||
flopr #(1) rbreg(clk, reset, (PCSrcE | PrivilegedChangePCM), ResolveBranchD);
|
//flopr #(1) rbreg(clk, reset, (PCSrcE | PrivilegedChangePCM), ResolveBranchD);
|
||||||
|
|
||||||
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
|
mux3 #(`XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
|
||||||
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
|
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
|
||||||
flopenl #(`XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, `RESET_VECTOR, PCF);
|
// flopenl #(`XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, `RESET_VECTOR, PCF);
|
||||||
|
flopenl #(`XLEN) pcreg(clk, reset, ~StallF, PCNextF, `RESET_VECTOR, PCF);
|
||||||
|
|
||||||
// pcadder
|
// pcadder
|
||||||
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
|
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
module csr (
|
module csr (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic FlushW,
|
input logic FlushW, StallW,
|
||||||
input logic [31:0] InstrM,
|
input logic [31:0] InstrM,
|
||||||
input logic [`XLEN-1:0] PCM, SrcAM,
|
input logic [`XLEN-1:0] PCM, SrcAM,
|
||||||
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module csrsr (
|
module csrsr (
|
||||||
input logic clk, reset,
|
input logic clk, reset, StallW,
|
||||||
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
|
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
|
||||||
input logic TrapM, FloatRegWriteW,
|
input logic TrapM, FloatRegWriteW,
|
||||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||||
@ -118,7 +118,7 @@ module csrsr (
|
|||||||
STATUS_MIE <= 0; // Per Priv 3.3
|
STATUS_MIE <= 0; // Per Priv 3.3
|
||||||
STATUS_SIE <= `S_SUPPORTED;
|
STATUS_SIE <= `S_SUPPORTED;
|
||||||
STATUS_UIE <= `U_SUPPORTED;
|
STATUS_UIE <= `U_SUPPORTED;
|
||||||
end else begin
|
end else if (~StallW) begin
|
||||||
if (WriteMSTATUSM) begin
|
if (WriteMSTATUSM) begin
|
||||||
STATUS_SUM_INT <= CSRWriteValM[18];
|
STATUS_SUM_INT <= CSRWriteValM[18];
|
||||||
STATUS_MPRV_INT <= CSRWriteValM[17];
|
STATUS_MPRV_INT <= CSRWriteValM[17];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// exceptions.sv
|
// privileged.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 5 January 2021
|
// Written: David_Harris@hmc.edu 5 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
@ -45,7 +45,7 @@ module privileged (
|
|||||||
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
||||||
input logic [4:0] SetFflagsM,
|
input logic [4:0] SetFflagsM,
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
input logic FlushD, FlushE, FlushM, StallD
|
input logic FlushD, FlushE, FlushM, StallD, StallW
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
|
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
|
||||||
@ -81,8 +81,8 @@ module privileged (
|
|||||||
|
|
||||||
// PrivilegeMode FSM
|
// PrivilegeMode FSM
|
||||||
always_comb
|
always_comb
|
||||||
if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode)
|
/* if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) // moved reset to flop
|
||||||
else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
else */ if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||||
else if (uretM) NextPrivilegeModeM = `U_MODE;
|
else if (uretM) NextPrivilegeModeM = `U_MODE;
|
||||||
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
||||||
@ -96,7 +96,7 @@ module privileged (
|
|||||||
else NextPrivilegeModeM = `M_MODE;
|
else NextPrivilegeModeM = `M_MODE;
|
||||||
end else NextPrivilegeModeM = PrivilegeModeW;
|
end else NextPrivilegeModeM = PrivilegeModeW;
|
||||||
|
|
||||||
flop #(2) privmodereg(clk, NextPrivilegeModeM, PrivilegeModeW);
|
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW);
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// decode privileged instructions
|
// decode privileged instructions
|
||||||
|
@ -37,6 +37,7 @@ module dtim (
|
|||||||
|
|
||||||
logic [`XLEN-1:0] RAM[0:65535];
|
logic [`XLEN-1:0] RAM[0:65535];
|
||||||
logic [18:0] HWADDR;
|
logic [18:0] HWADDR;
|
||||||
|
logic [`XLEN-1:0] HREADTim0;
|
||||||
|
|
||||||
// logic [`XLEN-1:0] write;
|
// logic [`XLEN-1:0] write;
|
||||||
logic [15:0] entry;
|
logic [15:0] entry;
|
||||||
@ -44,27 +45,28 @@ module dtim (
|
|||||||
logic [3:0] busycount;
|
logic [3:0] busycount;
|
||||||
|
|
||||||
// busy FSM to extend READY signal
|
// busy FSM to extend READY signal
|
||||||
/* always_ff @(posedge HCLK, negedge HRESETn)
|
always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
if (~HRESETn) begin
|
if (~HRESETn) begin
|
||||||
HREADYTim <= 1;
|
HREADYTim <= 1;
|
||||||
end else begin
|
end else begin
|
||||||
if (HREADYTim & HSELTim) begin
|
if (HREADYTim & HSELTim) begin
|
||||||
busycount <= 0;
|
busycount <= 0;
|
||||||
HREADYTim <= 0;
|
HREADYTim <= #1 0;
|
||||||
end else if (~HREADYTim) begin
|
end else if (~HREADYTim) begin
|
||||||
if (busycount == 0) begin // TIM latency, for testing purposes
|
if (busycount == 2) begin // TIM latency, for testing purposes
|
||||||
HREADYTim <= 1;
|
HREADYTim <= #1 1;
|
||||||
end else begin
|
end else begin
|
||||||
busycount <= busycount + 1;
|
busycount <= busycount + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end*/
|
end
|
||||||
always_ff @(posedge HCLK, negedge HRESETn)
|
|
||||||
|
/* always_ff @(posedge HCLK, negedge HRESETn)
|
||||||
if (~HRESETn) begin
|
if (~HRESETn) begin
|
||||||
HREADYTim <= 0;
|
HREADYTim <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
HREADYTim <= HSELTim; // always respond one cycle later
|
HREADYTim <= HSELTim; // always respond one cycle later
|
||||||
end
|
end */
|
||||||
|
|
||||||
|
|
||||||
assign memread = MemRWtim[1];
|
assign memread = MemRWtim[1];
|
||||||
@ -74,76 +76,31 @@ module dtim (
|
|||||||
assign HRESPTim = 0; // OK
|
assign HRESPTim = 0; // OK
|
||||||
// assign HREADYTim = 1; // Respond immediately; *** extend this
|
// assign HREADYTim = 1; // Respond immediately; *** extend this
|
||||||
|
|
||||||
// word aligned reads
|
|
||||||
/* generate
|
|
||||||
if (`XLEN==64)
|
|
||||||
assign #2 entry = HADDR[18:3];
|
|
||||||
else
|
|
||||||
assign #2 entry = HADDR[17:2];
|
|
||||||
endgenerate */
|
|
||||||
// assign HREADTim = RAM[entry];
|
|
||||||
// assign HREADTim = HREADYTim ? RAM[entry] : ~RAM[entry]; // *** temproary mess up read value before ready
|
|
||||||
|
|
||||||
// write each byte based on the byte mask
|
|
||||||
// UInstantiate a byte-writable memory here if possible
|
|
||||||
// and drop tihs masking logic. Otherwise, use the masking
|
|
||||||
// from dmem
|
|
||||||
/*generate
|
|
||||||
|
|
||||||
if (`XLEN==64) begin
|
|
||||||
always_comb begin
|
|
||||||
write=HREADTim;
|
|
||||||
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
|
|
||||||
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
|
|
||||||
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
|
|
||||||
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
|
|
||||||
if (ByteMaskM[4]) write[39:32] = HWDATA[39:32];
|
|
||||||
if (ByteMaskM[5]) write[47:40] = HWDATA[47:40];
|
|
||||||
if (ByteMaskM[6]) write[55:48] = HWDATA[55:48];
|
|
||||||
if (ByteMaskM[7]) write[63:56] = HWDATA[63:56];
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk)
|
|
||||||
if (memwrite) RAM[HADDR[18:3]] <= write;
|
|
||||||
end else begin // 32-bit
|
|
||||||
always_comb begin
|
|
||||||
write=HREADTim;
|
|
||||||
if (ByteMaskM[0]) write[7:0] = HWDATA[7:0];
|
|
||||||
if (ByteMaskM[1]) write[15:8] = HWDATA[15:8];
|
|
||||||
if (ByteMaskM[2]) write[23:16] = HWDATA[23:16];
|
|
||||||
if (ByteMaskM[3]) write[31:24] = HWDATA[31:24];
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk)
|
|
||||||
if (memwrite) RAM[HADDR[17:2]] <= write;
|
|
||||||
end
|
|
||||||
endgenerate */
|
|
||||||
|
|
||||||
// Model memory read and write
|
// Model memory read and write
|
||||||
// If write occurs at end of phase (rising edge of clock),
|
|
||||||
// then read of same address on next cycle won't work. Would need to bypass.
|
|
||||||
// Faking for now with negedge clock write. Will need to adjust this to
|
|
||||||
// match capabilities of FPGA or actual chip RAM.
|
|
||||||
// Also, writes occuring later than reads throws off single ported RAM that
|
|
||||||
// might be asked to write on one instruction and read on the next and would need
|
|
||||||
// to stall because both accesses happen on same cycle with AHB delay
|
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN == 64) begin
|
if (`XLEN == 64) begin
|
||||||
always_ff @(negedge HCLK)
|
// always_ff @(negedge HCLK)
|
||||||
if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
|
// if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
|
||||||
always_ff @(posedge HCLK) begin
|
always_ff @(posedge HCLK) begin
|
||||||
//if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
|
//if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
|
||||||
HWADDR <= HADDR;
|
HWADDR <= HADDR;
|
||||||
HREADTim <= RAM[HADDR[17:3]];
|
HREADTim0 <= RAM[HADDR[17:3]];
|
||||||
|
if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
always_ff @(negedge HCLK)
|
// always_ff @(negedge HCLK)
|
||||||
if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
|
// if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
|
||||||
always_ff @(posedge HCLK) begin
|
always_ff @(posedge HCLK) begin
|
||||||
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
|
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
|
||||||
HWADDR <= HADDR;
|
HWADDR <= HADDR;
|
||||||
HREADTim <= RAM[HADDR[17:2]];
|
HREADTim0 <= RAM[HADDR[17:2]];
|
||||||
|
if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
assign HREADTim = HREADYTim ? HREADTim0 : 'bz;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
##################################
|
##################################
|
||||||
# testgen-ADD-SUB.py
|
# testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py
|
||||||
#
|
#
|
||||||
# David_Harris@hmc.edu 19 January 2021
|
# David_Harris@hmc.edu 19 January 2021
|
||||||
#
|
#
|
||||||
@ -19,11 +19,34 @@ from random import getrandbits
|
|||||||
# functions
|
# functions
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
def computeExpected(a, b, test):
|
def twoscomp(a):
|
||||||
|
amsb = a >> (xlen-1)
|
||||||
|
alsbs = ((1 << (xlen-1)) - 1) & a
|
||||||
|
if (amsb):
|
||||||
|
asigned = a - (1<<xlen)
|
||||||
|
else:
|
||||||
|
asigned = a
|
||||||
|
#print("a: " + str(a) + " amsb: "+str(amsb)+ " alsbs: " + str(alsbs) + " asigned: "+str(asigned))
|
||||||
|
return asigned
|
||||||
|
|
||||||
|
def computeExpected(a, b, test, xlen):
|
||||||
|
asigned = twoscomp(a)
|
||||||
|
bsigned = twoscomp(b)
|
||||||
|
|
||||||
if (test == "ADD"):
|
if (test == "ADD"):
|
||||||
return a + b
|
return a + b
|
||||||
elif (test == "SUB"):
|
elif (test == "SUB"):
|
||||||
return a - b
|
return a - b
|
||||||
|
elif (test == "SLT"):
|
||||||
|
return asigned < bsigned
|
||||||
|
elif (test == "SLTU"):
|
||||||
|
return a < b
|
||||||
|
elif (test == "XOR"):
|
||||||
|
return a ^ b
|
||||||
|
elif (test == "OR"):
|
||||||
|
return a | b
|
||||||
|
elif (test == "AND"):
|
||||||
|
return a & b
|
||||||
else:
|
else:
|
||||||
die("bad test name ", test)
|
die("bad test name ", test)
|
||||||
# exit(1)
|
# exit(1)
|
||||||
@ -37,9 +60,9 @@ def randRegs():
|
|||||||
else:
|
else:
|
||||||
return reg1, reg2, reg3
|
return reg1, reg2, reg3
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
def writeVector(a, b, storecmd, xlen):
|
||||||
global testnum
|
global testnum
|
||||||
expected = computeExpected(a, b, test)
|
expected = computeExpected(a, b, test, xlen)
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
expected = expected % 2**xlen # drop carry if necessary
|
||||||
if (expected < 0): # take twos complement
|
if (expected < 0): # take twos complement
|
||||||
expected = 2**xlen + expected
|
expected = 2**xlen + expected
|
||||||
@ -65,7 +88,7 @@ def writeVector(a, b, storecmd):
|
|||||||
##################################
|
##################################
|
||||||
|
|
||||||
# change these to suite your tests
|
# change these to suite your tests
|
||||||
tests = ["ADD", "SUB"]
|
tests = ["ADD", "SUB", "SLT", "SLTU", "XOR", "OR", "AND"]
|
||||||
author = "David_Harris@hmc.edu & Katherine Parry"
|
author = "David_Harris@hmc.edu & Katherine Parry"
|
||||||
xlens = [32, 64]
|
xlens = [32, 64]
|
||||||
numrand = 100;
|
numrand = 100;
|
||||||
@ -111,11 +134,11 @@ for xlen in xlens:
|
|||||||
# print directed and random test vectors
|
# print directed and random test vectors
|
||||||
for a in corners:
|
for a in corners:
|
||||||
for b in corners:
|
for b in corners:
|
||||||
writeVector(a, b, storecmd)
|
writeVector(a, b, storecmd, xlen)
|
||||||
for i in range(0,numrand):
|
for i in range(0,numrand):
|
||||||
a = getrandbits(xlen)
|
a = getrandbits(xlen)
|
||||||
b = getrandbits(xlen)
|
b = getrandbits(xlen)
|
||||||
writeVector(a, b, storecmd)
|
writeVector(a, b, storecmd, xlen)
|
||||||
|
|
||||||
|
|
||||||
# print footer
|
# print footer
|
154
wally-pipelined/testgen/testgen-SLL-SRL-SRA.py
Executable file
154
wally-pipelined/testgen/testgen-SLL-SRL-SRA.py
Executable file
@ -0,0 +1,154 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
##################################
|
||||||
|
# testgen-SLL-SRL-SRA.py
|
||||||
|
#
|
||||||
|
# David_Harris@hmc.edu 19 January 2021
|
||||||
|
#
|
||||||
|
# Generate directed and random test vectors for RISC-V Design Validation.
|
||||||
|
##################################
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# libraries
|
||||||
|
##################################
|
||||||
|
from datetime import datetime
|
||||||
|
from random import randint
|
||||||
|
from random import seed
|
||||||
|
from random import getrandbits
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# functions
|
||||||
|
##################################
|
||||||
|
|
||||||
|
def twoscomp(a):
|
||||||
|
amsb = a >> (xlen-1)
|
||||||
|
alsbs = ((1 << (xlen-1)) - 1) & a
|
||||||
|
if (amsb):
|
||||||
|
asigned = a - (1<<xlen)
|
||||||
|
else:
|
||||||
|
asigned = a
|
||||||
|
#print("a: " + str(a) + " amsb: "+str(amsb)+ " alsbs: " + str(alsbs) + " asigned: "+str(asigned))
|
||||||
|
return asigned
|
||||||
|
|
||||||
|
def computeExpected(a, b, test, xlen):
|
||||||
|
asigned = twoscomp(a)
|
||||||
|
b = b % xlen
|
||||||
|
if (test == "SLL"):
|
||||||
|
return a << b
|
||||||
|
elif (test == "SRL"):
|
||||||
|
return a >> b
|
||||||
|
elif (test == "SRA"):
|
||||||
|
return asigned >> b
|
||||||
|
else:
|
||||||
|
die("bad test name ", test)
|
||||||
|
# exit(1)
|
||||||
|
|
||||||
|
def randRegs():
|
||||||
|
reg1 = randint(1,31)
|
||||||
|
reg2 = randint(1,31)
|
||||||
|
reg3 = randint(1,31)
|
||||||
|
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
||||||
|
return randRegs()
|
||||||
|
else:
|
||||||
|
return reg1, reg2, reg3
|
||||||
|
|
||||||
|
def writeVector(a, b, storecmd, xlen):
|
||||||
|
global testnum
|
||||||
|
expected = computeExpected(a, b, test, xlen)
|
||||||
|
expected = expected % 2**xlen # drop carry if necessary
|
||||||
|
if (expected < 0): # take twos complement
|
||||||
|
expected = 2**xlen + expected
|
||||||
|
reg1, reg2, reg3 = randRegs()
|
||||||
|
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
||||||
|
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b)
|
||||||
|
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
||||||
|
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
||||||
|
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
||||||
|
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n"
|
||||||
|
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
||||||
|
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+formatstr.format(expected)+")\n"
|
||||||
|
f.write(lines)
|
||||||
|
if (xlen == 32):
|
||||||
|
line = formatrefstr.format(expected)+"\n"
|
||||||
|
else:
|
||||||
|
line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n"
|
||||||
|
r.write(line)
|
||||||
|
testnum = testnum+1
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# main body
|
||||||
|
##################################
|
||||||
|
|
||||||
|
# change these to suite your tests
|
||||||
|
tests = ["SLL", "SRL", "SRA"]
|
||||||
|
author = "David_Harris@hmc.edu"
|
||||||
|
xlens = [32, 64]
|
||||||
|
numrand = 48
|
||||||
|
|
||||||
|
# setup
|
||||||
|
seed(0) # make tests reproducible
|
||||||
|
|
||||||
|
# generate files for each test
|
||||||
|
for xlen in xlens:
|
||||||
|
formatstrlen = str(int(xlen/4))
|
||||||
|
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
|
||||||
|
formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
|
||||||
|
if (xlen == 32):
|
||||||
|
storecmd = "sw"
|
||||||
|
wordsize = 4
|
||||||
|
else:
|
||||||
|
storecmd = "sd"
|
||||||
|
wordsize = 8
|
||||||
|
for test in tests:
|
||||||
|
corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1,
|
||||||
|
2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1]
|
||||||
|
if (xlen == 32):
|
||||||
|
shamt = [0, 1, 2, 3, 4, 8, 15, 16, 29, 30, 31]
|
||||||
|
else:
|
||||||
|
shamt = [0, 1, 3, 8, 15, 16, 29, 31, 32, 47, 48, 62, 63]
|
||||||
|
|
||||||
|
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
||||||
|
basename = "WALLY-" + test
|
||||||
|
fname = imperaspath + "src/" + basename + ".S"
|
||||||
|
refname = imperaspath + "references/" + basename + ".reference_output"
|
||||||
|
testnum = 0
|
||||||
|
|
||||||
|
# print custom header part
|
||||||
|
f = open(fname, "w")
|
||||||
|
r = open(refname, "w")
|
||||||
|
line = "///////////////////////////////////////////\n"
|
||||||
|
f.write(line)
|
||||||
|
lines="// "+fname+ "\n// " + author + "\n"
|
||||||
|
f.write(lines)
|
||||||
|
line ="// Created " + str(datetime.now())
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# insert generic header
|
||||||
|
h = open("testgen_header.S", "r")
|
||||||
|
for line in h:
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# print directed and random test vectors
|
||||||
|
for a in corners:
|
||||||
|
for b in shamt:
|
||||||
|
writeVector(a, b, storecmd, xlen)
|
||||||
|
for i in range(0,numrand):
|
||||||
|
a = getrandbits(xlen)
|
||||||
|
b = getrandbits(xlen)
|
||||||
|
writeVector(a, b, storecmd, xlen)
|
||||||
|
|
||||||
|
|
||||||
|
# print footer
|
||||||
|
h = open("testgen_footer.S", "r")
|
||||||
|
for line in h:
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# Finish
|
||||||
|
lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n"
|
||||||
|
lines = lines + "\nRV_COMPLIANCE_DATA_END\n"
|
||||||
|
f.write(lines)
|
||||||
|
f.close()
|
||||||
|
r.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user