2021-01-24 22:10:00 +00:00
|
|
|
`include "wally-config.vh"
|
2021-01-21 21:17:34 +00:00
|
|
|
|
2021-01-24 22:10:00 +00:00
|
|
|
module testbench_busybear();
|
2021-01-21 21:17:34 +00:00
|
|
|
|
2021-01-21 22:55:05 +00:00
|
|
|
logic clk, reset;
|
2021-01-24 22:10:00 +00:00
|
|
|
logic [`XLEN-1:0] WriteDataM, DataAdrM;
|
2021-01-21 22:55:05 +00:00
|
|
|
logic [1:0] MemRWM;
|
|
|
|
logic [31:0] GPIOPinsIn;
|
|
|
|
logic [31:0] GPIOPinsOut, GPIOPinsEn;
|
2021-01-21 21:17:34 +00:00
|
|
|
|
|
|
|
// instantiate device to be tested
|
2021-01-24 22:10:00 +00:00
|
|
|
logic [`XLEN-1:0] PCF, ReadDataM;
|
2021-01-21 22:55:05 +00:00
|
|
|
logic [31:0] InstrF;
|
|
|
|
logic [7:0] ByteMaskM;
|
|
|
|
logic InstrAccessFaultF, DataAccessFaultM;
|
|
|
|
logic TimerIntM, SwIntM; // from CLINT
|
|
|
|
logic ExtIntM = 0; // not yet connected
|
2021-01-23 22:52:05 +00:00
|
|
|
|
|
|
|
// for now, seem to need these to be zero until we get a better idea
|
|
|
|
assign InstrAccessFaultF = 0;
|
|
|
|
assign DataAccessFaultM = 0;
|
2021-01-21 22:55:05 +00:00
|
|
|
|
|
|
|
// instantiate processor and memories
|
2021-01-24 22:10:00 +00:00
|
|
|
wallypipelinedhart #(.PCSTART('h1000)) dut(.ALUResultM(DataAdrM), .*);
|
2021-01-21 21:17:34 +00:00
|
|
|
|
|
|
|
// initialize test
|
|
|
|
initial
|
|
|
|
begin
|
2021-01-21 22:55:05 +00:00
|
|
|
reset <= 1; # 22; reset <= 0;
|
2021-01-21 21:17:34 +00:00
|
|
|
end
|
2021-01-22 19:11:17 +00:00
|
|
|
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
// read pc trace file
|
|
|
|
integer data_file_PC, scan_file_PC;
|
2021-01-22 19:11:17 +00:00
|
|
|
initial begin
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
data_file_PC = $fopen("busybear-testgen/parsedPC.txt", "r");
|
|
|
|
if (data_file_PC == 0) begin
|
2021-01-22 19:11:17 +00:00
|
|
|
$display("file couldn't be opened");
|
|
|
|
$stop;
|
|
|
|
end
|
|
|
|
end
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
|
|
|
|
// read register trace file
|
|
|
|
integer data_file_rf, scan_file_rf;
|
|
|
|
initial begin
|
|
|
|
data_file_rf = $fopen("busybear-testgen/parsedRegs.txt", "r");
|
|
|
|
if (data_file_rf == 0) begin
|
|
|
|
$display("file couldn't be opened");
|
|
|
|
$stop;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// read memreads trace file
|
|
|
|
integer data_file_mem, scan_file_mem;
|
|
|
|
initial begin
|
|
|
|
data_file_mem = $fopen("busybear-testgen/parsedMemRead.txt", "r");
|
|
|
|
if (data_file_mem == 0) begin
|
|
|
|
$display("file couldn't be opened");
|
|
|
|
$stop;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-22 20:05:58 +00:00
|
|
|
logic [63:0] rfExpected[31:1];
|
|
|
|
logic [63:0] pcExpected;
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
// I apologize for this hack, I don't have a clue how to properly work with packed arrays
|
|
|
|
logic [64*32:64] rf;
|
|
|
|
genvar i;
|
|
|
|
generate
|
|
|
|
for(i=1; i<32; i++) begin
|
|
|
|
assign rf[i*64+63:i*64] = dut.dp.regf.rf[i];
|
|
|
|
end
|
|
|
|
endgenerate
|
2021-01-22 19:11:17 +00:00
|
|
|
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
always @(rf) begin
|
|
|
|
for(int j=1; j<32; j++) begin
|
|
|
|
// read 31 integer registers
|
|
|
|
scan_file_rf = $fscanf(data_file_rf, "%x\n", rfExpected[j]);
|
|
|
|
// check things!
|
|
|
|
if (rf[j*64+63 -: 64] != rfExpected[j]) begin
|
2021-01-23 21:42:17 +00:00
|
|
|
$display("%t ps: rf[%0d] does not equal rf expected: %x, %x", $time, j, rf[j*64+63 -: 64], rfExpected[j]);
|
|
|
|
// $stop;
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// this might need to change
|
|
|
|
always @(MemRWM or DataAdrM) begin
|
|
|
|
if (MemRWM != 0) begin
|
|
|
|
scan_file_mem = $fscanf(data_file_mem, "%x\n", ReadDataM);
|
2021-01-22 20:05:58 +00:00
|
|
|
end
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
end
|
|
|
|
|
2021-01-24 00:01:44 +00:00
|
|
|
logic speculative, nextSpec;
|
|
|
|
initial begin
|
|
|
|
speculative = 0;
|
|
|
|
nextSpec = 0;
|
|
|
|
end
|
change how testbench reads data
we're not sure if this is a good idea, but for now, we broke things up into 3 seperate
files, each read seperately. One for pc and instructions, one for registers, and one for
memory reads. Each is scrolled through essentially independantly: new pc data is read and checked
whenever pc changes, new register data is checked whenever any register changes, and a new mem
read value is gotten whenever DataAdrM or MemRWM changes and MemRWM is not zero. I'm not super
sure about the last one. Currently it looks like things should be working, but it goes wrong after,
like, 3 instructions.
2021-01-23 01:27:01 +00:00
|
|
|
|
|
|
|
always @(PCF) begin
|
2021-01-24 00:01:44 +00:00
|
|
|
speculative <= nextSpec;
|
|
|
|
if (speculative) begin
|
|
|
|
speculative <= (PCF != pcExpected);
|
|
|
|
end
|
|
|
|
if (~speculative) begin
|
|
|
|
// first read instruction
|
|
|
|
scan_file_PC = $fscanf(data_file_PC, "%x\n", InstrF);
|
|
|
|
// then expected PC value
|
|
|
|
scan_file_PC = $fscanf(data_file_PC, "%x\n", pcExpected);
|
|
|
|
// are we at a branch/jump?
|
|
|
|
case (InstrF[6:0]) //todo: add C versions of these
|
|
|
|
7'b1101111, //JAL
|
|
|
|
7'b1100111, //JALR
|
|
|
|
7'b1100011: //B
|
|
|
|
nextSpec <= 1;
|
|
|
|
default:
|
|
|
|
nextSpec <= 0;
|
|
|
|
endcase
|
|
|
|
|
|
|
|
//check things!
|
|
|
|
if ((~nextSpec) && (PCF !== pcExpected)) begin
|
|
|
|
$display("%t ps: PC does not equal PC expected: %x, %x", $time, PCF, pcExpected);
|
|
|
|
// $stop;
|
|
|
|
end
|
2021-01-22 20:05:58 +00:00
|
|
|
end
|
2021-01-22 19:11:17 +00:00
|
|
|
end
|
|
|
|
|
2021-01-23 02:14:45 +00:00
|
|
|
// Track names of instructions
|
|
|
|
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
|
|
|
logic [31:0] InstrW;
|
|
|
|
instrNameDecTB dec(InstrF, InstrFName);
|
2021-01-24 22:10:00 +00:00
|
|
|
instrTrackerTB it(clk, reset, dut.dp.FlushE,
|
2021-01-23 02:14:45 +00:00
|
|
|
dut.dp.InstrDecompD, dut.dp.InstrE,
|
|
|
|
dut.dp.InstrM, InstrW,
|
|
|
|
InstrDName, InstrEName, InstrMName, InstrWName);
|
2021-01-21 21:17:34 +00:00
|
|
|
|
|
|
|
// generate clock to sequence tests
|
|
|
|
always
|
|
|
|
begin
|
2021-01-21 22:55:05 +00:00
|
|
|
clk <= 1; # 5; clk <= 0; # 5;
|
2021-01-21 21:17:34 +00:00
|
|
|
end
|
|
|
|
|
2021-01-21 22:55:05 +00:00
|
|
|
//// check results
|
|
|
|
//always @(negedge clk)
|
|
|
|
// begin
|
|
|
|
// if(MemWrite) begin
|
|
|
|
// if(DataAdr === 84 & WriteData === 71) begin
|
|
|
|
// $display("Simulation succeeded");
|
|
|
|
// $stop;
|
|
|
|
// end else if (DataAdr !== 80) begin
|
|
|
|
// $display("Simulation failed");
|
|
|
|
// $stop;
|
|
|
|
// end
|
|
|
|
// end
|
|
|
|
// end
|
2021-01-21 21:17:34 +00:00
|
|
|
endmodule
|