package VRAM_Test; import Assert::*; import StmtFSM::*; import GetPut::*; import ClientServer::*; import Connectable::*; import Vector::*; import MemArbiter::*; import Testing::*; import VRAM::*; interface FakeVRAM; interface VRAMServer server; method Action next_response(VRAMResponse resp); method Maybe#(VRAMRequest) last_request(); endinterface module mkFakeVRAM(FakeVRAM); Reg#(Maybe#(VRAMRequest)) req <- mkReg(tagged Invalid); Reg#(Maybe#(VRAMResponse)) resp <- mkReg(tagged Invalid); interface VRAMServer server; interface Put request; method Action put(r); req <= tagged Valid r; endmethod endinterface interface Get response; method ActionValue#(VRAMResponse) get() if (resp matches tagged Valid .respval &&& req matches tagged Valid .reqval &&& reqval.data matches tagged Invalid); resp <= tagged Invalid; return respval; endmethod endinterface endinterface method Action next_response(r) if (resp matches tagged Invalid); resp <= tagged Valid r; endmethod method Maybe#(VRAMRequest) last_request(); return req; endmethod endmodule module mkArbitratedVRAMServersTest(FSM); let testflags <- mkTestFlags(); let cycles <- mkCycleCounter(); let vram <- mkFakeVRAM(); MemArbiter#(3, VRAMAddr) arb <- mkPriorityMemArbiter(); Vector#(3, VRAMServer) ports <- mkArbitratedVRAMServers(vram.server, arb); function Action check_read(VRAMServer port, VRAMAddr want_addr, VRAMData want_data); return action let want_request = VRAMRequest{addr: want_addr, data: tagged Invalid}; if (testflags.verbose) $display("Last received VRAM request: ", fshow(vram.last_request), " want ", fshow(want_request)); dynamicAssert(vram.last_request == tagged Valid want_request, "wrong request seen by vram for read"); let got <- port.response.get(); if (testflags.verbose) $display("VRAM.read() = %0d, want %0d", got.data, want_data); dynamicAssert(got.data == want_data, "wrong data seen in vram read"); endaction; endfunction function Action check_write(VRAMAddr want_addr, VRAMData data); return action let want = VRAMRequest{addr: want_addr, data: tagged Valid data}; if (testflags.verbose) $display("Last received VRAM request: ", fshow(vram.last_request), " want ", fshow(want)); dynamicAssert(vram.last_request == tagged Valid want, "wrong request seen by vram for write"); endaction; endfunction let fsm <- mkFSM(seq // Single write ports[1].request.put(VRAMRequest{addr: 123, data: tagged Valid 42}); check_write(123, 42); // Single read vram.next_response(VRAMResponse{data: 23}); ports[1].request.put(VRAMRequest{addr: 124, data: tagged Invalid}); check_read(ports[1], 124, 23); // Concurrent ops, process port 1 response first to check // buffering allows port 0 op to finish and port 1 to proceed vram.next_response(VRAMResponse{data: 11}); par vram.next_response(VRAMResponse{data: 66}); ports[0].request.put(VRAMRequest{addr: 123, data: tagged Invalid}); ports[1].request.put(VRAMRequest{addr: 125, data: tagged Invalid}); endpar check_read(ports[1], 125, 66); check_read(ports[0], 125, 11); // note, 125 because the last op is still port 1's read endseq); return fsm; endmodule module mkTestFull(FSM); let testflags <- mkTestFlags(); let dut <- mkVRAM(4); let fsm <- mkFSM(seq dut.cpu.request.put(VRAMRequest{addr: 1, data: tagged Valid 42}); dut.cpu.request.put(VRAMRequest{addr: 1, data: tagged Invalid}); action let resp <- dut.cpu.response.get(); if (testflags.verbose) $display("vram read: ", fshow(resp)); dynamicAssert(resp.data == 42, "wrong data read after writing"); endaction endseq); return fsm; endmodule module mkTB(); let testGlue <- mkArbitratedVRAMServersTest(); let testFull <- mkTestFull(); runTest(100, mkTest("VRAM", seq mkTest("VRAM/Glue", seq testGlue.start(); await(testGlue.done); endseq); mkTest("VRAM/Full", seq testFull.start(); await(testFull.done); endseq); endseq)); endmodule endpackage