CORE: suppress some warnings
[yari.git] / shared / rtl / yari-core / yari.v
bloba6b6bcae49b2b7ecfc6d3726344402f09a5b08bb
1 // -----------------------------------------------------------------------
2 //
3 // Copyright 2008 Tommy Thorn - All Rights Reserved
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 // Bostom MA 02111-1307, USA; either version 2 of the License, or
9 // (at your option) any later version; incorporated herein by reference.
11 // -----------------------------------------------------------------------
13 `timescale 1ns/10ps
14 `include "asm.v"
15 `include "../soclib/pipeconnect.h"
18 `ifdef SIMULATE_MAIN
19 /* Conditional compilation removes a lot of annoying warnings during synthesis. */
20 module stallcheck(clock, stall, a);
21 parameter which = "?";
22 parameter id = -1;
23 parameter w = 1;
25 input clock;
26 input stall;
27 input [w-1:0] a;
29 reg stall_;
30 reg [w-1:0] a_;
32 always @(posedge clock) begin
33 {a_,stall_} <= {a,stall};
34 if (stall_ && a != a_)
35 $display("** %05d STALLCHECKER violation %d: was %x != now %x (%d)",
36 $time, id, a_, a, stall_);
37 end
38 endmodule
39 `endif
41 module yari(input wire clock
42 ,input wire rst
44 // Memory access
45 ,input mem_waitrequest
46 ,output [1:0] mem_id
47 ,output [29:0] mem_address
48 ,output mem_read
49 ,output mem_write
50 ,output [31:0] mem_writedata
51 ,output [3:0] mem_writedatamask
52 ,input [31:0] mem_readdata
53 ,input [1:0] mem_readdataid
55 ,output wire `REQ peripherals_req
56 ,input wire `RES peripherals_res
59 parameter FREQ = 0; // Frequency in Hz, should be passed down from the top-level
60 parameter debug = 1;
62 wire i1_valid, i2_valid;
63 wire [31:0] i1_pc, i2_pc;
65 wire i_valid;
66 wire i_valid_muxed;
67 wire [31:0] i_instr;
68 wire [31:0] i_instr_muxed;
69 wire [31:0] i_pc;
70 wire [31:0] i_pc_muxed;
71 wire [31:0] i_npc;
73 wire imem_waitrequest;
74 wire [29:0] imem_address;
75 wire imem_read;
76 wire [31:0] imem_readdata;
77 wire imem_readdatavalid;
79 wire d_valid;
80 wire d_illegal_instr;
81 wire [31:0] d_instr;
82 wire [31:0] d_pc;
83 wire [31:0] d_npc;
84 wire [ 5:0] d_opcode;
85 wire [ 5:0] d_fn;
86 wire [ 4:0] d_rd;
87 wire [ 5:0] d_rs;
88 wire [ 5:0] d_rt;
89 wire [ 4:0] d_sa;
90 wire [31:0] d_target;
91 wire [ 5:0] d_wbr;
92 wire d_has_delay_slot;
93 wire [31:0] d_op1_val;
94 wire [31:0] d_op2_val;
95 wire [31:0] d_rt_val;
96 wire [31:0] d_simm;
98 wire d_restart;
99 wire [31:0] d_restart_pc;
100 wire d_flush_X;
101 wire d_load_use_hazard;
103 wire x_valid;
104 wire [31:0] x_instr;
105 wire x_is_delay_slot;
106 wire [31:0] x_pc;
107 wire [ 5:0] x_opcode;
108 wire [31:0] x_op1_val;
109 wire [ 5:0] x_rt;
110 wire [31:0] x_rt_val;
111 wire [ 5:0] x_wbr;
112 wire [31:0] x_res;
114 wire x_synci;
115 wire [31:0] x_synci_a;
117 wire x_restart;
118 wire [31:0] x_restart_pc;
119 wire x_flush_D;
121 wire m_valid;
122 wire [31:0] m_instr;
123 wire [31:0] m_pc;
124 wire [ 5:0] m_wbr;
125 wire [31:0] m_res;
127 wire m_restart;
128 wire [31:0] m_restart_pc;
130 wire dmem_waitrequest;
131 wire [29:0] dmem_address;
132 wire dmem_read;
133 wire dmem_write;
134 wire [31:0] dmem_writedata;
135 wire [ 3:0] dmem_writedatamask;
136 wire [31:0] dmem_readdata;
137 wire dmem_readdatavalid;
139 wire [31:0] perf_branch_hazard;
140 wire [31:0] perf_dcache_misses;
141 wire [31:0] perf_delay_slot_bubble;
142 wire [31:0] perf_div_hazard;
143 wire [31:0] perf_icache_misses;
144 wire [31:0] perf_io_load_busy;
145 wire [31:0] perf_io_store_busy;
146 wire [31:0] perf_load_hit_store_hazard;
147 wire [31:0] perf_load_use_hazard;
148 wire [31:0] perf_mult_hazard;
149 wire [47:0] perf_retired_inst;
150 wire [31:0] perf_sb_full;
153 reg [9:0] initialized = 0;
154 always @(posedge clock) initialized <= {initialized[8:0],~rst};
156 // XXX It would be nice to make this a bit more general and merge
157 // it with the interrupt mechanism (still to come)
158 wire boot = initialized[7] & ~initialized[8];
160 wire restart = d_restart | x_restart | m_restart;
161 wire [31:0] restart_pc = (d_restart ? d_restart_pc :
162 m_restart ? m_restart_pc :
163 /*********/ x_restart_pc);
164 wire flush_I = restart;
165 wire flush_D = m_restart | x_flush_D;
166 wire flush_X = m_restart | d_flush_X;
168 stage_I stI(.clock(clock)
169 ,.kill(~initialized[8])
170 ,.restart(restart)
171 ,.restart_pc(restart_pc)
172 ,.synci(x_synci)
173 ,.synci_a(x_synci_a)
175 ,.imem_waitrequest(imem_waitrequest)
176 ,.imem_address(imem_address)
177 ,.imem_read(imem_read)
178 ,.imem_readdata(imem_readdata)
179 ,.imem_readdatavalid(imem_readdatavalid)
181 // Outputs
182 ,.i1_valid(i1_valid)
183 ,.i1_pc(i1_pc)
184 ,.i2_valid(i2_valid)
185 ,.i2_pc(i2_pc)
187 ,.i_valid(i_valid)
188 ,.i_instr(i_instr)
189 ,.i_pc(i_pc)
190 ,.i_npc(i_npc)
191 ,.perf_icache_misses(perf_icache_misses));
193 stage_D stD(.clock(clock),
194 .i_valid(i_valid & ~flush_I),
195 .i_instr(i_instr),
196 .i_pc(i_pc),
197 .i_npc(i_npc),
199 .i_valid_muxed(i_valid_muxed),
200 .i_pc_muxed(i_pc_muxed),
201 .i_instr_muxed(i_instr_muxed),
203 .x_valid(x_valid & ~flush_X),
204 .x_wbr(x_wbr),
205 .x_res(x_res),
207 .m_valid(m_valid),
208 .m_pc(m_pc), // XXX for debugging only
209 .m_wbr(m_wbr),
210 .m_res(m_res),
212 // Outputs, mostly derived from d_instr
213 .d_valid(d_valid),
214 .d_illegal_instr(d_illegal_instr),
215 .d_instr(d_instr),
216 .d_pc(d_pc),
217 .d_npc(d_npc),
218 .d_opcode(d_opcode),
219 .d_fn(d_fn),
220 .d_rd(d_rd),
221 .d_rs(d_rs),
222 .d_rt(d_rt),
223 .d_sa(d_sa),
224 .d_target(d_target),
225 .d_wbr(d_wbr),
226 .d_has_delay_slot(d_has_delay_slot),
228 // Register lookups
229 .d_op1_val(d_op1_val),
230 .d_op2_val(d_op2_val),
231 .d_rt_val(d_rt_val),
232 .d_simm(d_simm),
233 .d_restart(d_restart),
234 .d_restart_pc(d_restart_pc),
235 .d_flush_X(d_flush_X),
236 .d_load_use_hazard(d_load_use_hazard),
238 .flush_D(flush_D),
239 .perf_delay_slot_bubble(perf_delay_slot_bubble),
240 .perf_retired_inst(perf_retired_inst)
243 stage_X stX(.clock(clock),
245 .restart(restart),
246 .restart_pc(restart_pc),
248 .d_valid(d_valid & ~flush_D),
249 .d_instr(d_instr),
250 .d_pc(d_pc),
251 .d_npc(d_npc),
252 .d_opcode(d_opcode),
253 .d_fn(d_fn),
254 .d_rd(d_rd),
255 .d_rs(d_rs),
256 .d_rt(d_rt),
257 .d_sa(d_sa),
258 .d_target(d_target),
259 .d_wbr(d_wbr),
260 .d_has_delay_slot(d_has_delay_slot),
262 .d_op1_val(d_op1_val),
263 .d_op2_val(d_op2_val),
264 .d_rt_val(d_rt_val),
265 .d_simm(d_simm),
266 .d_restart(d_restart),
267 .d_restart_pc(d_restart_pc),
268 .d_load_use_hazard(d_load_use_hazard),
270 .m_valid(m_valid),
271 .m_wbr(m_wbr),
273 // Results from this stage
274 .x_valid(x_valid),
275 .x_instr(x_instr), // XXX for debugging only
276 .x_is_delay_slot(x_is_delay_slot),
277 .x_pc(x_pc),
278 .x_opcode(x_opcode),
279 .x_op1_val(x_op1_val),
280 .x_rt(x_rt),
281 .x_rt_val(x_rt_val),
282 .x_wbr(x_wbr),
283 .x_res(x_res),
285 .x_synci(x_synci),
286 .x_synci_a(x_synci_a),
288 .x_restart(x_restart),
289 .x_restart_pc(x_restart_pc),
290 .x_flush_D(x_flush_D),
292 .perf_branch_hazard(perf_branch_hazard),
293 .perf_dcache_misses(perf_dcache_misses),
294 .perf_delay_slot_bubble(perf_delay_slot_bubble),
295 .perf_div_hazard(perf_div_hazard),
296 .perf_icache_misses(perf_icache_misses),
297 .perf_io_load_busy(perf_io_load_busy),
298 .perf_io_store_busy(perf_io_store_busy),
299 .perf_load_hit_store_hazard(perf_load_hit_store_hazard),
300 .perf_load_use_hazard(perf_load_use_hazard),
301 .perf_mult_hazard(perf_mult_hazard),
302 .perf_retired_inst(perf_retired_inst),
303 .perf_sb_full(perf_sb_full)
305 defparam stX.FREQ = FREQ;
307 stage_M stM(.clock(clock),
309 // XXX Rebooting on illegal instruction is harsh
310 .boot(boot | d_illegal_instr),
311 .boot_pc('hBFC00000),
313 .d_simm(d_simm),
314 .d_op1_val(d_op1_val),
316 .x_valid(x_valid & ~flush_X),
317 .x_instr(x_instr),
318 .x_is_delay_slot(x_is_delay_slot),
319 .x_pc(x_pc),
320 .x_opcode(x_opcode),
321 .x_op1_val(x_op1_val),
322 .x_rt(x_rt),
323 .x_rt_val(x_rt_val),
324 .x_wbr(x_wbr),
325 .x_res(x_res)
327 ,.dmem_waitrequest(dmem_waitrequest)
328 ,.dmem_address(dmem_address)
329 ,.dmem_read(dmem_read)
330 ,.dmem_write(dmem_write)
331 ,.dmem_writedata(dmem_writedata)
332 ,.dmem_writedatamask(dmem_writedatamask)
333 ,.dmem_readdata(dmem_readdata)
334 ,.dmem_readdatavalid(dmem_readdatavalid)
337 .peripherals_req(peripherals_req),
338 .peripherals_res(peripherals_res),
340 .m_valid(m_valid),
341 .m_instr(m_instr),
342 .m_pc(m_pc),
343 .m_wbr(m_wbr),
344 .m_res(m_res),
346 .m_restart(m_restart),
347 .m_restart_pc(m_restart_pc),
349 .perf_dcache_misses(perf_dcache_misses),
350 .perf_io_load_busy(perf_io_load_busy),
351 .perf_io_store_busy(perf_io_store_busy),
352 .perf_load_hit_store_hazard(perf_load_hit_store_hazard),
353 .perf_sb_full(perf_sb_full)
358 * Memory arbitration. "Hopefully so simple that I can do it all
359 * right here".
360 * Static priority - bad idea in general, but ok here.
361 * Key decision: dmem port gets priority. Why? Imagine it was
362 * the other way around and both miss in their caches. IF will
363 * keep emitting bubbles while filling, but ME will repeatedly
364 * restart the load and flush the pipe. At least with ME filling
365 * first, we get to execute the few instructions already in the
366 * pipe while waiting for IF. One of them could be a MUL!
368 parameter ID_DC = 2'd1;
369 parameter ID_IC = 2'd2;
370 wire dmem_strobe = dmem_read | dmem_write;
372 assign mem_id = dmem_strobe ? ID_DC : ID_IC;
373 assign mem_address = dmem_strobe ? dmem_address : imem_address;
374 assign mem_read = dmem_strobe ? dmem_read : imem_read;
375 assign mem_write = dmem_write;
376 assign mem_writedata = dmem_writedata;
377 assign mem_writedatamask = dmem_writedatamask;
379 assign dmem_waitrequest = mem_waitrequest;
380 assign dmem_readdata = mem_readdata;
381 assign dmem_readdatavalid = mem_readdataid == ID_DC;
383 assign imem_waitrequest = mem_waitrequest | dmem_strobe;
384 assign imem_readdata = mem_readdata;
385 assign imem_readdatavalid = mem_readdataid == ID_IC;
387 `ifdef SIMULATE_MAIN
388 always @(posedge clock) if (debug) begin
389 if (d_restart)
390 $display("%05d RESTART %x FROM DE", $time, d_restart_pc);
391 else if (m_restart)
392 $display("%05d RESTART %x FROM ME", $time, m_restart_pc);
393 else if (x_restart)
394 $display("%05d RESTART %x FROM EX", $time, x_restart_pc);
396 $display(
397 "%05dz %x/0 I %8x D %8x:%8x X %8x:%8x:%8x>%2x M %8x:%8x>%2x W %8x:%8x>%2x",
399 $time,
401 {flush_X,flush_D,flush_I},
403 // IF
404 i1_valid ? i1_pc : 'hZ,
406 // DE
407 i_pc_muxed, i_valid_muxed ? i_instr_muxed : 'hZ,
409 // EX
410 d_pc, d_valid & ~flush_D ? d_op1_val : 'hZ,
411 d_valid & ~flush_D ? d_op2_val : 'hZ,
412 d_valid & ~flush_D ? d_wbr : 8'hZ,
414 // ME
415 x_pc, x_valid & ~flush_X ? x_res : 'hZ,
416 x_valid & ~flush_X ? x_wbr : 8'hZ,
418 // WB
419 m_pc, m_valid ? m_res : 'hZ,
420 m_valid ? m_wbr : 8'hZ);
422 `endif
423 endmodule