punk@1
|
1
|
punk@1
|
2 import ClientServer::*;
|
punk@1
|
3 import FIFO::*;
|
punk@1
|
4 import GetPut::*;
|
punk@1
|
5 import DefaultValue::*;
|
punk@1
|
6 import SceMi::*;
|
punk@1
|
7 import Clocks::*;
|
punk@1
|
8
|
punk@1
|
9 import Core::*;
|
punk@1
|
10 import ProcTypes::*;
|
punk@1
|
11 import Processor::*;
|
punk@1
|
12 import DataCacheBlocking::*;
|
punk@1
|
13 import InstCacheBlocking::*;
|
punk@1
|
14
|
punk@1
|
15 interface DutWrapper;
|
punk@1
|
16 interface Core core;
|
punk@1
|
17
|
punk@1
|
18 // We use a Bit#(1) instead of void because Bluespec Sce-Mi doesn't appear
|
punk@1
|
19 // to support sending void over the PCIe link yet.
|
punk@1
|
20 interface Put#(Bit#(1)) doreset;
|
punk@1
|
21 endinterface
|
punk@1
|
22
|
punk@1
|
23 (* synthesize *)
|
punk@1
|
24 module [Module] mkDutWrapper (DutWrapper);
|
punk@1
|
25
|
punk@1
|
26 Clock clk <- exposeCurrentClock;
|
punk@1
|
27 MakeResetIfc myrst <- mkReset(2000, True, clk);
|
punk@1
|
28
|
punk@1
|
29 Core coreifc <- mkCore(reset_by myrst.new_rst);
|
punk@1
|
30
|
punk@1
|
31 // For tracing
|
punk@1
|
32 Reg#(int) cycle <- mkReg(0);
|
punk@1
|
33 rule printCycles;
|
punk@1
|
34 cycle <= cycle + 1;
|
punk@1
|
35 $fdisplay(stderr, " => Cycle = %d", cycle);
|
punk@1
|
36 endrule
|
punk@1
|
37
|
punk@1
|
38 interface Core core = coreifc;
|
punk@1
|
39
|
punk@1
|
40 interface Put doreset;
|
punk@1
|
41 method Action put(Bit#(1) x);
|
punk@1
|
42 cycle <= 0;
|
punk@1
|
43 myrst.assertReset();
|
punk@1
|
44 endmethod
|
punk@1
|
45 endinterface
|
punk@1
|
46
|
punk@1
|
47 endmodule
|
punk@1
|
48
|
punk@1
|
49 module [SceMiModule] mkSceMiLayer();
|
punk@1
|
50
|
punk@1
|
51 SceMiClockConfiguration conf = defaultValue;
|
punk@1
|
52
|
punk@1
|
53 SceMiClockPortIfc clk_port <- mkSceMiClockPort(conf);
|
punk@1
|
54 DutWrapper dut <- buildDut(mkDutWrapper, clk_port);
|
punk@1
|
55
|
punk@1
|
56 Empty mmem <- mkClientXactor(dut.core.mmem_client, clk_port);
|
punk@1
|
57 Empty tohost <- mkCPUToHostXactor(dut.core.tohost, clk_port);
|
punk@1
|
58 Empty stats <- mkCoreStatsXactor(dut.core.stats, clk_port);
|
punk@1
|
59 Empty doreset <- mkPutXactor(dut.doreset, clk_port);
|
punk@1
|
60
|
punk@1
|
61 Empty shutdown <- mkShutdownXactor();
|
punk@1
|
62
|
punk@1
|
63 endmodule
|
punk@1
|
64
|
punk@1
|
65 module [SceMiModule] mkCPUToHostXactor#(CPUToHost tohost, SceMiClockPortIfc clk_port ) (Empty);
|
punk@1
|
66
|
punk@1
|
67 // Access the controlled clock and reset
|
punk@1
|
68 Clock cclock = clk_port.cclock;
|
punk@1
|
69 Reset creset = clk_port.creset;
|
punk@1
|
70
|
punk@1
|
71 // req belongs entirely to the controlled clock domain. We'll use the
|
punk@1
|
72 // clock domain crossings already implemented by the Bluespec people (in
|
punk@1
|
73 // the Put and Get transactors), because they know about such things
|
punk@1
|
74 // better than I do.
|
punk@1
|
75 FIFO#(int) req <- mkFIFO(clocked_by cclock, reset_by creset);
|
punk@1
|
76
|
punk@1
|
77 Get#(Bit#(32)) resp = interface Get;
|
punk@1
|
78 method ActionValue#(Bit#(32)) get();
|
punk@1
|
79 req.deq();
|
punk@1
|
80 return tohost.cpuToHost(req.first());
|
punk@1
|
81 endmethod
|
punk@1
|
82 endinterface;
|
punk@1
|
83
|
punk@1
|
84 Empty request <- mkPutXactor(toPut(req), clk_port);
|
punk@1
|
85 Empty response <- mkGetXactor(resp, clk_port);
|
punk@1
|
86
|
punk@1
|
87 endmodule
|
punk@1
|
88
|
punk@1
|
89 typedef enum {
|
punk@1
|
90 DCACHE_ACCESSES, DCACHE_MISSES, DCACHE_WRITEBACKS,
|
punk@1
|
91 ICACHE_ACCESSES, ICACHE_MISSES, ICACHE_EVICTIONS,
|
punk@1
|
92 PROC_INST, PROC_CYCLES
|
punk@1
|
93 } StatID deriving(Bits, Eq);
|
punk@1
|
94
|
punk@1
|
95 module [SceMiModule] mkCoreStatsXactor#(CoreStats stats, SceMiClockPortIfc clk_port) (Empty);
|
punk@1
|
96
|
punk@1
|
97 // Access the controlled clock and reset
|
punk@1
|
98 Clock cclock = clk_port.cclock;
|
punk@1
|
99 Reset creset = clk_port.creset;
|
punk@1
|
100
|
punk@1
|
101 // Again, req and resp belong to the controlled clock domain.
|
punk@1
|
102 FIFO#(StatID) req <- mkFIFO(clocked_by cclock, reset_by creset);
|
punk@1
|
103 FIFO#(Stat) resp <- mkFIFO(clocked_by cclock, reset_by creset);
|
punk@1
|
104
|
punk@1
|
105 rule handleRequest (True);
|
punk@1
|
106 case (req.first())
|
punk@1
|
107 DCACHE_ACCESSES: begin
|
punk@1
|
108 let x <- stats.dcache.num_accesses.get();
|
punk@1
|
109 resp.enq(x);
|
punk@1
|
110 end
|
punk@1
|
111 DCACHE_MISSES: begin
|
punk@1
|
112 let x <- stats.dcache.num_misses.get();
|
punk@1
|
113 resp.enq(x);
|
punk@1
|
114 end
|
punk@1
|
115 DCACHE_WRITEBACKS: begin
|
punk@1
|
116 let x <- stats.dcache.num_writebacks.get();
|
punk@1
|
117 resp.enq(x);
|
punk@1
|
118 end
|
punk@1
|
119 ICACHE_ACCESSES: begin
|
punk@1
|
120 let x <- stats.icache.num_accesses.get();
|
punk@1
|
121 resp.enq(x);
|
punk@1
|
122 end
|
punk@1
|
123 ICACHE_MISSES: begin
|
punk@1
|
124 let x <- stats.icache.num_misses.get();
|
punk@1
|
125 resp.enq(x);
|
punk@1
|
126 end
|
punk@1
|
127 ICACHE_EVICTIONS: begin
|
punk@1
|
128 let x <- stats.icache.num_evictions.get();
|
punk@1
|
129 resp.enq(x);
|
punk@1
|
130 end
|
punk@1
|
131 PROC_INST: begin
|
punk@1
|
132 let x <- stats.proc.num_inst.get();
|
punk@1
|
133 resp.enq(x);
|
punk@1
|
134 end
|
punk@1
|
135 PROC_CYCLES: begin
|
punk@1
|
136 let x <- stats.proc.num_cycles.get();
|
punk@1
|
137 resp.enq(x);
|
punk@1
|
138 end
|
punk@1
|
139 endcase
|
punk@1
|
140 req.deq();
|
punk@1
|
141 endrule
|
punk@1
|
142
|
punk@1
|
143 Server#(StatID, Stat) server = interface Server;
|
punk@1
|
144 interface Get response = toGet(resp);
|
punk@1
|
145 interface Put request = toPut(req);
|
punk@1
|
146 endinterface;
|
punk@1
|
147
|
punk@1
|
148 Empty xx <- mkServerXactor(server, clk_port);
|
punk@1
|
149 endmodule
|
punk@1
|
150
|