forked from Github_Repos/cvw
More memory interface, ALU testgen
This commit is contained in:
parent
183a2dcfb5
commit
37dba8fd26
@ -38,9 +38,8 @@ module ahblite (
|
||||
// Signals from Instruction Cache
|
||||
input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram
|
||||
input logic InstrReadF,
|
||||
input logic ResolveBranchD,
|
||||
// input logic ResolveBranchD,
|
||||
output logic [31:0] InstrRData,
|
||||
// output logic IReady,
|
||||
// Signals from Data Cache
|
||||
input logic [`XLEN-1:0] MemPAdrM,
|
||||
input logic MemReadM, MemWriteM,
|
||||
@ -48,7 +47,6 @@ module ahblite (
|
||||
input logic [1:0] MemSizeM,
|
||||
// Return from bus
|
||||
output logic [`XLEN-1:0] ReadDataW,
|
||||
// output logic DReady,
|
||||
// AHB-Lite external signals
|
||||
input logic [`AHBW-1:0] HRDATA,
|
||||
input logic HREADY, HRESP,
|
||||
@ -61,14 +59,12 @@ module ahblite (
|
||||
output logic [3:0] HPROT,
|
||||
output logic [1:0] HTRANS,
|
||||
output logic HMASTLOCK,
|
||||
// Delayed signals for subword write
|
||||
// Delayed signals for writes
|
||||
output logic [2:0] HADDRD,
|
||||
output logic [3:0] HSIZED,
|
||||
output logic HWRITED,
|
||||
// Acknowledge
|
||||
output logic InstrAckD, MemAckW,
|
||||
// Stalls
|
||||
output logic InstrStall, DataStall
|
||||
output logic InstrStall,/*InstrUpdate, */DataStall
|
||||
);
|
||||
|
||||
logic GrantData;
|
||||
@ -81,12 +77,61 @@ module ahblite (
|
||||
assign HCLK = clk;
|
||||
assign HRESETn = ~reset;
|
||||
|
||||
// Arbitrate requests by giving data priority over instructions
|
||||
assign GrantData = MemReadM | MemWriteM;
|
||||
|
||||
// *** initially support HABW = XLEN
|
||||
|
||||
// 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;
|
||||
statetype AdrState, DataState, NextAdrState; // what is happening in the first and second phases of the bus
|
||||
always_ff @(posedge HCLK, negedge HRESETn)
|
||||
@ -117,13 +162,42 @@ module ahblite (
|
||||
assign MemAckW = (AdrState == MEMREAD || AdrState == MEMWRITE) && 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
|
||||
generate
|
||||
//if (`AHBW == 32) assign ISize = 3'b010; // 32-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
|
||||
endgenerate
|
||||
|
||||
/*
|
||||
// drive bus outputs
|
||||
assign HADDR = GrantData ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
||||
//assign HWDATA = WriteDataW;
|
||||
@ -134,41 +208,16 @@ module ahblite (
|
||||
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 HMASTLOCK = 0; // no locking supported
|
||||
|
||||
*/
|
||||
// Route signals to Instruction and Data Caches
|
||||
// *** assumes AHBW = XLEN
|
||||
assign InstrRData = HRDATAMasked[31:0];
|
||||
assign IReady = HREADY & InstrReadF & ~GrantData; // maybe unused?***
|
||||
// assign ReadDataW = HRDATAMasked;
|
||||
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
|
||||
flopenrc #(`XLEN) ReadDataWReg(clk, reset, FlushW, ~StallW, ReadDataM, ReadDataW);
|
||||
assign DReady = HREADY & GrantData; // ***unused?
|
||||
assign CaptureDataM = (BusState == MEMREAD) && (NextBusState != MEMREAD);
|
||||
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
|
||||
// Stall MEM stage if data is being accessed and bus isn't yet ready
|
||||
//assign DataStall = GrantData & ~HREADY;
|
||||
|
@ -47,6 +47,16 @@ module flopr #(parameter WIDTH = 8) (
|
||||
else q <= #1 d;
|
||||
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
|
||||
module flopenrc #(parameter WIDTH = 8) (
|
||||
input logic clk, reset, clear, en,
|
||||
|
@ -56,12 +56,12 @@ module hazard(
|
||||
|
||||
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
|
||||
assign StallDCause = LoadStallD; // stall in decode if instruction is a load dependent on previous
|
||||
assign StallECause = 0;
|
||||
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.
|
||||
assign StallF = StallD | StallFCause;
|
||||
|
@ -67,18 +67,20 @@ module ifu (
|
||||
|
||||
// *** put memory interface on here, InstrF becomes output
|
||||
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 StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
|
||||
//assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
|
||||
|
||||
// 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);
|
||||
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
|
||||
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
module csr (
|
||||
input logic clk, reset,
|
||||
input logic FlushW,
|
||||
input logic FlushW, StallW,
|
||||
input logic [31:0] InstrM,
|
||||
input logic [`XLEN-1:0] PCM, SrcAM,
|
||||
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
||||
|
@ -27,7 +27,7 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module csrsr (
|
||||
input logic clk, reset,
|
||||
input logic clk, reset, StallW,
|
||||
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM,
|
||||
input logic TrapM, FloatRegWriteW,
|
||||
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
|
||||
@ -118,7 +118,7 @@ module csrsr (
|
||||
STATUS_MIE <= 0; // Per Priv 3.3
|
||||
STATUS_SIE <= `S_SUPPORTED;
|
||||
STATUS_UIE <= `U_SUPPORTED;
|
||||
end else begin
|
||||
end else if (~StallW) begin
|
||||
if (WriteMSTATUSM) begin
|
||||
STATUS_SUM_INT <= CSRWriteValM[18];
|
||||
STATUS_MPRV_INT <= CSRWriteValM[17];
|
||||
|
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////
|
||||
// exceptions.sv
|
||||
// privileged.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 5 January 2021
|
||||
// Modified:
|
||||
@ -45,7 +45,7 @@ module privileged (
|
||||
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
||||
input logic [4:0] SetFflagsM,
|
||||
output logic [2:0] FRM_REGW,
|
||||
input logic FlushD, FlushE, FlushM, StallD
|
||||
input logic FlushD, FlushE, FlushM, StallD, StallW
|
||||
);
|
||||
|
||||
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
|
||||
@ -81,8 +81,8 @@ module privileged (
|
||||
|
||||
// PrivilegeMode FSM
|
||||
always_comb
|
||||
if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode)
|
||||
else if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||
/* if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode) // moved reset to flop
|
||||
else */ if (mretM) NextPrivilegeModeM = STATUS_MPP;
|
||||
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
|
||||
else if (uretM) NextPrivilegeModeM = `U_MODE;
|
||||
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
|
||||
@ -96,7 +96,7 @@ module privileged (
|
||||
else NextPrivilegeModeM = `M_MODE;
|
||||
end else NextPrivilegeModeM = PrivilegeModeW;
|
||||
|
||||
flop #(2) privmodereg(clk, NextPrivilegeModeM, PrivilegeModeW);
|
||||
flopenl #(2) privmodereg(clk, reset, ~StallW, NextPrivilegeModeM, `M_MODE, PrivilegeModeW);
|
||||
|
||||
///////////////////////////////////////////
|
||||
// decode privileged instructions
|
||||
|
@ -37,6 +37,7 @@ module dtim (
|
||||
|
||||
logic [`XLEN-1:0] RAM[0:65535];
|
||||
logic [18:0] HWADDR;
|
||||
logic [`XLEN-1:0] HREADTim0;
|
||||
|
||||
// logic [`XLEN-1:0] write;
|
||||
logic [15:0] entry;
|
||||
@ -44,27 +45,28 @@ module dtim (
|
||||
logic [3:0] busycount;
|
||||
|
||||
// busy FSM to extend READY signal
|
||||
/* always_ff @(posedge HCLK, negedge HRESETn)
|
||||
always_ff @(posedge HCLK, negedge HRESETn)
|
||||
if (~HRESETn) begin
|
||||
HREADYTim <= 1;
|
||||
end else begin
|
||||
if (HREADYTim & HSELTim) begin
|
||||
busycount <= 0;
|
||||
HREADYTim <= 0;
|
||||
HREADYTim <= #1 0;
|
||||
end else if (~HREADYTim) begin
|
||||
if (busycount == 0) begin // TIM latency, for testing purposes
|
||||
HREADYTim <= 1;
|
||||
if (busycount == 2) begin // TIM latency, for testing purposes
|
||||
HREADYTim <= #1 1;
|
||||
end else begin
|
||||
busycount <= busycount + 1;
|
||||
end
|
||||
end
|
||||
end*/
|
||||
always_ff @(posedge HCLK, negedge HRESETn)
|
||||
end
|
||||
|
||||
/* always_ff @(posedge HCLK, negedge HRESETn)
|
||||
if (~HRESETn) begin
|
||||
HREADYTim <= 0;
|
||||
end else begin
|
||||
HREADYTim <= HSELTim; // always respond one cycle later
|
||||
end
|
||||
end */
|
||||
|
||||
|
||||
assign memread = MemRWtim[1];
|
||||
@ -73,77 +75,32 @@ module dtim (
|
||||
// memwrite <= MemRWtim[0]; // delay memwrite to write phase
|
||||
assign HRESPTim = 0; // OK
|
||||
// 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
|
||||
// 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
|
||||
if (`XLEN == 64) begin
|
||||
always_ff @(negedge HCLK)
|
||||
if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
|
||||
// always_ff @(negedge HCLK)
|
||||
// if (memwrite) RAM[HWADDR[17:3]] <= HWDATA;
|
||||
always_ff @(posedge HCLK) begin
|
||||
//if (memwrite) RAM[HADDR[17:3]] <= HWDATA;
|
||||
HWADDR <= HADDR;
|
||||
HREADTim <= RAM[HADDR[17:3]];
|
||||
HREADTim0 <= RAM[HADDR[17:3]];
|
||||
if (memwrite && HREADYTim) RAM[HWADDR[17:3]] <= HWDATA;
|
||||
end
|
||||
end else begin
|
||||
always_ff @(negedge HCLK)
|
||||
if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
|
||||
// always_ff @(negedge HCLK)
|
||||
// if (memwrite) RAM[HWADDR[17:2]] <= HWDATA;
|
||||
always_ff @(posedge HCLK) begin
|
||||
//if (memwrite) RAM[HADDR[17:2]] <= HWDATA;
|
||||
HWADDR <= HADDR;
|
||||
HREADTim <= RAM[HADDR[17:2]];
|
||||
HREADTim0 <= RAM[HADDR[17:2]];
|
||||
if (memwrite && HREADYTim) RAM[HWADDR[17:2]] <= HWDATA;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign HREADTim = HREADYTim ? HREADTim0 : 'bz;
|
||||
endmodule
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python3
|
||||
##################################
|
||||
# testgen-ADD-SUB.py
|
||||
# testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py
|
||||
#
|
||||
# David_Harris@hmc.edu 19 January 2021
|
||||
#
|
||||
@ -19,11 +19,34 @@ from random import getrandbits
|
||||
# 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"):
|
||||
return a + b
|
||||
elif (test == "SUB"):
|
||||
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:
|
||||
die("bad test name ", test)
|
||||
# exit(1)
|
||||
@ -37,9 +60,9 @@ def randRegs():
|
||||
else:
|
||||
return reg1, reg2, reg3
|
||||
|
||||
def writeVector(a, b, storecmd):
|
||||
def writeVector(a, b, storecmd, xlen):
|
||||
global testnum
|
||||
expected = computeExpected(a, b, test)
|
||||
expected = computeExpected(a, b, test, xlen)
|
||||
expected = expected % 2**xlen # drop carry if necessary
|
||||
if (expected < 0): # take twos complement
|
||||
expected = 2**xlen + expected
|
||||
@ -65,7 +88,7 @@ def writeVector(a, b, storecmd):
|
||||
##################################
|
||||
|
||||
# change these to suite your tests
|
||||
tests = ["ADD", "SUB"]
|
||||
tests = ["ADD", "SUB", "SLT", "SLTU", "XOR", "OR", "AND"]
|
||||
author = "David_Harris@hmc.edu & Katherine Parry"
|
||||
xlens = [32, 64]
|
||||
numrand = 100;
|
||||
@ -111,11 +134,11 @@ for xlen in xlens:
|
||||
# print directed and random test vectors
|
||||
for a in corners:
|
||||
for b in corners:
|
||||
writeVector(a, b, storecmd)
|
||||
writeVector(a, b, storecmd, xlen)
|
||||
for i in range(0,numrand):
|
||||
a = getrandbits(xlen)
|
||||
b = getrandbits(xlen)
|
||||
writeVector(a, b, storecmd)
|
||||
writeVector(a, b, storecmd, xlen)
|
||||
|
||||
|
||||
# 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