punk@1: punk@1: import ClientServer::*; punk@1: import FIFO::*; punk@1: import GetPut::*; punk@1: import DefaultValue::*; punk@1: import SceMi::*; punk@1: import Clocks::*; punk@1: punk@1: import Core::*; punk@1: import ProcTypes::*; punk@1: import Processor::*; punk@1: import DataCacheBlocking::*; punk@1: import InstCacheBlocking::*; punk@1: punk@1: interface DutWrapper; punk@1: interface Core core; punk@1: punk@1: // We use a Bit#(1) instead of void because Bluespec Sce-Mi doesn't appear punk@1: // to support sending void over the PCIe link yet. punk@1: interface Put#(Bit#(1)) doreset; punk@1: endinterface punk@1: punk@1: (* synthesize *) punk@1: module [Module] mkDutWrapper (DutWrapper); punk@1: punk@1: Clock clk <- exposeCurrentClock; punk@1: MakeResetIfc myrst <- mkReset(2000, True, clk); punk@1: punk@1: Core coreifc <- mkCore(reset_by myrst.new_rst); punk@1: punk@1: // For tracing punk@1: Reg#(int) cycle <- mkReg(0); punk@1: rule printCycles; punk@1: cycle <= cycle + 1; punk@1: $fdisplay(stderr, " => Cycle = %d", cycle); punk@1: endrule punk@1: punk@1: interface Core core = coreifc; punk@1: punk@1: interface Put doreset; punk@1: method Action put(Bit#(1) x); punk@1: cycle <= 0; punk@1: myrst.assertReset(); punk@1: endmethod punk@1: endinterface punk@1: punk@1: endmodule punk@1: punk@1: module [SceMiModule] mkSceMiLayer(); punk@1: punk@1: SceMiClockConfiguration conf = defaultValue; punk@1: punk@1: SceMiClockPortIfc clk_port <- mkSceMiClockPort(conf); punk@1: DutWrapper dut <- buildDut(mkDutWrapper, clk_port); punk@1: punk@1: Empty mmem <- mkClientXactor(dut.core.mmem_client, clk_port); punk@1: Empty tohost <- mkCPUToHostXactor(dut.core.tohost, clk_port); punk@1: Empty stats <- mkCoreStatsXactor(dut.core.stats, clk_port); punk@1: Empty doreset <- mkPutXactor(dut.doreset, clk_port); punk@1: punk@1: Empty shutdown <- mkShutdownXactor(); punk@1: punk@1: endmodule punk@1: punk@1: module [SceMiModule] mkCPUToHostXactor#(CPUToHost tohost, SceMiClockPortIfc clk_port ) (Empty); punk@1: punk@1: // Access the controlled clock and reset punk@1: Clock cclock = clk_port.cclock; punk@1: Reset creset = clk_port.creset; punk@1: punk@1: // req belongs entirely to the controlled clock domain. We'll use the punk@1: // clock domain crossings already implemented by the Bluespec people (in punk@1: // the Put and Get transactors), because they know about such things punk@1: // better than I do. punk@1: FIFO#(int) req <- mkFIFO(clocked_by cclock, reset_by creset); punk@1: punk@1: Get#(Bit#(32)) resp = interface Get; punk@1: method ActionValue#(Bit#(32)) get(); punk@1: req.deq(); punk@1: return tohost.cpuToHost(req.first()); punk@1: endmethod punk@1: endinterface; punk@1: punk@1: Empty request <- mkPutXactor(toPut(req), clk_port); punk@1: Empty response <- mkGetXactor(resp, clk_port); punk@1: punk@1: endmodule punk@1: punk@1: typedef enum { punk@1: DCACHE_ACCESSES, DCACHE_MISSES, DCACHE_WRITEBACKS, punk@1: ICACHE_ACCESSES, ICACHE_MISSES, ICACHE_EVICTIONS, punk@1: PROC_INST, PROC_CYCLES punk@1: } StatID deriving(Bits, Eq); punk@1: punk@1: module [SceMiModule] mkCoreStatsXactor#(CoreStats stats, SceMiClockPortIfc clk_port) (Empty); punk@1: punk@1: // Access the controlled clock and reset punk@1: Clock cclock = clk_port.cclock; punk@1: Reset creset = clk_port.creset; punk@1: punk@1: // Again, req and resp belong to the controlled clock domain. punk@1: FIFO#(StatID) req <- mkFIFO(clocked_by cclock, reset_by creset); punk@1: FIFO#(Stat) resp <- mkFIFO(clocked_by cclock, reset_by creset); punk@1: punk@1: rule handleRequest (True); punk@1: case (req.first()) punk@1: DCACHE_ACCESSES: begin punk@1: let x <- stats.dcache.num_accesses.get(); punk@1: resp.enq(x); punk@1: end punk@1: DCACHE_MISSES: begin punk@1: let x <- stats.dcache.num_misses.get(); punk@1: resp.enq(x); punk@1: end punk@1: DCACHE_WRITEBACKS: begin punk@1: let x <- stats.dcache.num_writebacks.get(); punk@1: resp.enq(x); punk@1: end punk@1: ICACHE_ACCESSES: begin punk@1: let x <- stats.icache.num_accesses.get(); punk@1: resp.enq(x); punk@1: end punk@1: ICACHE_MISSES: begin punk@1: let x <- stats.icache.num_misses.get(); punk@1: resp.enq(x); punk@1: end punk@1: ICACHE_EVICTIONS: begin punk@1: let x <- stats.icache.num_evictions.get(); punk@1: resp.enq(x); punk@1: end punk@1: PROC_INST: begin punk@1: let x <- stats.proc.num_inst.get(); punk@1: resp.enq(x); punk@1: end punk@1: PROC_CYCLES: begin punk@1: let x <- stats.proc.num_cycles.get(); punk@1: resp.enq(x); punk@1: end punk@1: endcase punk@1: req.deq(); punk@1: endrule punk@1: punk@1: Server#(StatID, Stat) server = interface Server; punk@1: interface Get response = toGet(resp); punk@1: interface Put request = toPut(req); punk@1: endinterface; punk@1: punk@1: Empty xx <- mkServerXactor(server, clk_port); punk@1: endmodule punk@1: