view modules/bluespec/Pygar/core/Processor.bsv @ 11:50af57801d6e pygar svn.12

[svn r12] working on getting audio pipe processor working
author punk
date Sun, 25 Apr 2010 08:31:47 -0400
parents 74716e9a81cc
children 394aa40fd812
line wrap: on
line source
1 /// The MIT License
3 // Copyright (c) 2009 Massachusetts Institute of Technology
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
23 import Connectable::*;
24 import GetPut::*;
25 import ClientServer::*;
26 import RegFile::*;
28 import FIFO::*;
29 import FIFOF::*;
30 import SFIFO::*;
31 import RWire::*;
33 import Trace::*;
34 import BFIFO::*;
35 import MemTypes::*;
36 import ProcTypes::*;
37 import BRegFile::*;
38 import BranchPred::*;
39 //import PathTypes::*; This is only there to force the debugging
41 //AWB includes
42 `include "asim/provides/low_level_platform_interface.bsh"
43 `include "asim/provides/soft_connections.bsh"
44 `include "asim/provides/common_services.bsh"
46 // Local includes
47 //`include "asim/provides/processor_library.bsh" (included above directly)
48 `include "asim/rrr/remote_server_stub_PROCESSORSYSTEMRRR.bsh"
49 `include "asim/provides/common_services.bsh"
50 `include "asim/dict/STATS_PROCESSOR.bsh"
52 // Local includes. Look for the correspondingly named .awb files
53 // workspace/labs/src/mit-6.375/modules/bluespec/mit-6.375/common/
54 // to find the actual Bluespec files which are used to generate
55 // these includes. These files are specific to this audio processing
56 // pipeline
58 `include "asim/provides/audio_processor_types.bsh"
60 interface CPUToHost;
61 method Bit#(32) cpuToHost(int req);
62 endinterface
64 interface Proc;
66 // Interface from processor to caches
67 interface Client#(DataReq,DataResp) dmem_client;
68 interface Client#(InstReq,InstResp) imem_client;
70 // Interface for enabling/disabling statistics on the rest of the core
71 interface Get#(Bool) statsEn_get;
73 // Interface to host
74 interface CPUToHost tohost;
76 // Interface to Audio Pipeline
77 interface Audio audio;
79 endinterface
81 //The full interface for this is as below in the common file for audioProcessorTypes.bsv
82 interface Audio;
83 interface Put#(AudioProcessorUnit) audioSampleInput;
84 interface Get#(AudioProcessorUnit) audioSampleOutput;
85 endinterface
87 typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits);
89 //-----------------------------------------------------------
90 // Register file module
91 //-----------------------------------------------------------
93 interface BRFile;
94 method Action wr( Rindx rindx, Bit#(32) data );
95 method Bit#(32) rd1( Rindx rindx );
96 method Bit#(32) rd2( Rindx rindx );
97 endinterface
99 module mkBRFile( BRFile );
101 RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile();
103 method Action wr( Rindx rindx, Bit#(32) data );
104 rfile.upd( rindx, data );
105 endmethod
107 method Bit#(32) rd1( Rindx rindx );
108 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
109 endmethod
111 method Bit#(32) rd2( Rindx rindx );
112 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
113 endmethod
115 endmodule
117 //-----------------------------------------------------------
118 // Helper functions
119 //-----------------------------------------------------------
121 function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );
122 return zeroExtend( pack( signedLT(val1,val2) ) );
123 endfunction
125 function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );
126 return zeroExtend( pack( val1 < val2 ) );
127 endfunction
129 function Bit#(32) rshft( Bit#(32) val );
130 return zeroExtend(val[4:0]);
131 endfunction
134 //-----------------------------------------------------------
135 // Find funct for wbQ
136 //-----------------------------------------------------------
137 function Bool findwbf(Rindx fVal, WBResult cmpVal);
138 case (cmpVal) matches
139 tagged WB_ALU {data:.res, dest:.rd} :
140 return (fVal == rd);
141 tagged WB_Load .rd :
142 return (fVal == rd);
143 tagged WB_Store .st :
144 return False;
145 tagged WB_Host .x :
146 return False;
147 endcase
148 endfunction
151 //-----------------------------------------------------------
152 // Stall funct for wbQ
153 //-----------------------------------------------------------
154 function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f);
155 case (inst) matches
156 // -- Memory Ops ------------------------------------------------
157 tagged LW .it :
158 return f.find(it.rbase);
159 tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} :
160 return (f.find(addr) || f.find2(dreg));
162 // -- Simple Ops ------------------------------------------------
163 tagged ADDIU .it : return f.find(it.rsrc);
164 tagged SLTI .it : return f.find(it.rsrc);
165 tagged SLTIU .it : return f.find(it.rsrc);
166 tagged ANDI .it : return f.find(it.rsrc);
167 tagged ORI .it : return f.find(it.rsrc);
168 tagged XORI .it : return f.find(it.rsrc);
170 tagged LUI .it : return f.find(it.rdst); //this rds/wrs itself
171 tagged SLL .it : return f.find(it.rsrc);
172 tagged SRL .it : return f.find(it.rsrc);
173 tagged SRA .it : return f.find(it.rsrc);
174 tagged SLLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));
175 tagged SRLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));
176 tagged SRAV .it : return (f.find(it.rsrc) || f.find(it.rshamt));
177 tagged ADDU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
178 tagged SUBU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
179 tagged AND .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
180 tagged OR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
181 tagged XOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
182 tagged NOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
183 tagged SLT .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
184 tagged SLTU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
187 // -- Branches --------------------------------------------------
189 tagged BLEZ .it : return (f.find(it.rsrc));
190 tagged BGTZ .it : return (f.find(it.rsrc));
191 tagged BLTZ .it : return (f.find(it.rsrc));
192 tagged BGEZ .it : return (f.find(it.rsrc));
193 tagged BEQ .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
194 tagged BNE .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
196 // -- Jumps -----------------------------------------------------
198 tagged J .it : return False;
199 tagged JR .it : return f.find(it.rsrc);
200 tagged JALR .it : return f.find(it.rsrc);
201 tagged JAL .it : return False;
203 // -- Cop0 ------------------------------------------------------
205 tagged MTC0 .it : return f.find(it.rsrc);
206 tagged MFC0 .it : return False;
208 // -- Illegal ---------------------------------------------------
210 default : return False;
212 endcase
213 endfunction
214 //-----------------------------------------------------------
215 // Reference processor
216 //-----------------------------------------------------------
219 //(* doc = "synthesis attribute ram_style mkProc distributed;" *)
220 //(* synthesize *)
222 module [CONNECTED_MODULE] mkProc( Proc );
224 //-----------------------------------------------------------
225 // Debug port
227 ServerStub_PROCESSORSYSTEMRRR server_stub <- mkServerStub_PROCESSORSYSTEMRRR();
230 //-----------------------------------------------------------
231 // State
233 // Standard processor state
235 Reg#(Addr) pc <- mkReg(32'h00001000);
236 Reg#(Epoch) epoch <- mkReg(0);
237 Reg#(Stage) stage <- mkReg(PCgen);
238 BRFile rf <- mkBRFile;
240 // Branch Prediction
241 BranchPred bp <- mkBranchPred();
242 FIFO#(PCStat) execpc <- mkLFIFO();
244 // Pipelines
245 FIFO#(PCStat) pcQ <-mkSizedFIFO(3);
246 SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf);
248 Reg#(Bit#(32)) cp0_tohost <- mkReg(0);
249 Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);
250 Reg#(Bool) cp0_statsEn <- mkReg(False);
252 // Memory request/response state
254 FIFO#(InstReq) instReqQ <- mkBFIFO1();
255 FIFO#(InstResp) instRespQ <- mkFIFO();
257 FIFO#(DataReq) dataReqQ <- mkBFIFO1();
258 FIFO#(DataResp) dataRespQ <- mkFIFO();
260 // Audio I/O
261 FIFO#(AudioProcessorUnit) inAudioFifo <- mkFIFO;
262 FIFO#(AudioProcessorUnit) outAudioFifo <- mkFIFO;
265 // Statistics state (2010)
266 // Reg#(Stat) num_cycles <- mkReg(0);
267 // Reg#(Stat) num_inst <- mkReg(0);
269 //Or:
270 // Statistics state
271 STAT num_cycles <- mkStatCounter(`STATS_PROCESSOR_CYCLE_COUNT);
272 STAT num_inst <- mkStatCounter(`STATS_PROCESSOR_INST_COUNT);
274 //-----------------------------------------------------------
275 // Rules
277 (* descending_urgency = "exec, pcgen" *)
278 rule pcgen; //( stage == PCgen );
279 let pc_plus4 = pc + 4;
281 traceTiny("mkProc", "pc",pc);
282 traceTiny("mkProc", "pcgen","P");
283 instReqQ.enq( LoadReq{ addr:pc, tag:epoch} );
285 let next_pc = bp.get(pc);
286 if (next_pc matches tagged Valid .npc)
287 begin
288 pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch});
289 pc <= npc;
290 end
291 else
292 begin
293 pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch});
294 pc <= pc_plus4;
295 end
297 endrule
299 rule discard (instRespQ.first() matches tagged LoadResp .ld
300 &&& ld.tag != epoch);
301 traceTiny("mkProc", "stage", "D");
302 instRespQ.deq();
303 endrule
305 (* conflict_free = "exec, writeback" *)
306 rule exec (instRespQ.first() matches tagged LoadResp.ld
307 &&& (ld.tag == epoch)
308 &&& unpack(ld.data) matches .inst
309 &&& !stall(inst, wbQ));
311 // Some abbreviations
312 let sext = signExtend;
313 let zext = zeroExtend;
314 let sra = signedShiftRight;
316 // Get the instruction
318 instRespQ.deq();
319 Instr inst
320 = case ( instRespQ.first() ) matches
321 tagged LoadResp .ld : return unpack(ld.data);
322 tagged StoreResp .st : return ?;
323 endcase;
325 // Get the PC info
326 let instrpc = pcQ.first().qpc;
327 let pc_plus4 = instrpc + 4;
329 Bool branchTaken = False;
330 Addr newPC = pc_plus4;
332 // Tracing
333 traceTiny("mkProc", "exec","X");
334 traceTiny("mkProc", "exInstTiny",inst);
335 traceFull("mkProc", "exInstFull",inst);
337 case ( inst ) matches
339 // -- Memory Ops ------------------------------------------------
341 tagged LW .it :
342 begin
343 Addr addr = rf.rd1(it.rbase) + sext(it.offset);
344 dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } );
345 wbQ.enq(tagged WB_Load it.rdst);
346 end
348 tagged SW .it :
349 begin
350 Addr addr = rf.rd1(it.rbase) + sext(it.offset);
351 dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } );
352 wbQ.enq(tagged WB_Store);
353 end
355 // -- Simple Ops ------------------------------------------------
357 tagged ADDIU .it :
358 begin
359 Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm);
360 wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst});
361 end
362 tagged SLTI .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )});
363 tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) });
364 tagged ANDI .it :
365 begin
366 Bit#(32) zext_it_imm = zext(it.imm);
367 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} );
368 end
369 tagged ORI .it :
370 begin
371 Bit#(32) zext_it_imm = zext(it.imm);
372 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} );
373 end
374 tagged XORI .it :
375 begin
376 Bit#(32) zext_it_imm = zext(it.imm);
377 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )});
378 end
379 tagged LUI .it :
380 begin
381 Bit#(32) zext_it_imm = zext(it.imm);
382 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) });
383 end
385 tagged SLL .it :
386 begin
387 Bit#(32) zext_it_shamt = zext(it.shamt);
388 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} );
389 end
390 tagged SRL .it :
391 begin
392 Bit#(32) zext_it_shamt = zext(it.shamt);
393 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )});
394 end
395 tagged SRA .it :
396 begin
397 Bit#(32) zext_it_shamt = zext(it.shamt);
398 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )});
399 end
400 tagged SLLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )});
401 tagged SRLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} );
402 tagged SRAV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) });
403 tagged ADDU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} );
404 tagged SUBU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} );
405 tagged AND .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} );
406 tagged OR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} );
407 tagged XOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} );
408 tagged NOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} );
409 tagged SLT .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });
410 tagged SLTU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });
412 // -- Branches --------------------------------------------------
414 tagged BLEZ .it :
415 if ( signedLE( rf.rd1(it.rsrc), 0 ) )
416 begin
417 newPC = pc_plus4 + (sext(it.offset) << 2);
418 branchTaken = True;
419 end
421 tagged BGTZ .it :
422 if ( signedGT( rf.rd1(it.rsrc), 0 ) )
423 begin
424 newPC = pc_plus4 + (sext(it.offset) << 2);
425 branchTaken = True;
426 end
428 tagged BLTZ .it :
429 if ( signedLT( rf.rd1(it.rsrc), 0 ) )
430 begin
431 newPC = pc_plus4 + (sext(it.offset) << 2);
432 branchTaken = True;
433 end
435 tagged BGEZ .it :
436 if ( signedGE( rf.rd1(it.rsrc), 0 ) )
437 begin
438 newPC = pc_plus4 + (sext(it.offset) << 2);
439 branchTaken = True;
440 end
442 tagged BEQ .it :
443 if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )
444 begin
445 newPC = pc_plus4 + (sext(it.offset) << 2);
446 branchTaken = True;
447 end
449 tagged BNE .it :
450 if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )
451 begin
452 newPC = pc_plus4 + (sext(it.offset) << 2);
453 branchTaken = True;
454 end
456 // -- Jumps -----------------------------------------------------
458 tagged J .it :
459 begin
460 newPC = { pc_plus4[31:28], it.target, 2'b0 };
461 branchTaken = True;
462 end
464 tagged JR .it :
465 begin
466 newPC = rf.rd1(it.rsrc);
467 branchTaken = True;
468 end
470 tagged JAL .it :
471 begin
472 wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 });
473 newPC = { pc_plus4[31:28], it.target, 2'b0 };
474 branchTaken = True;
475 end
477 tagged JALR .it :
478 begin
479 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 });
480 newPC = rf.rd1(it.rsrc);
481 branchTaken = True;
482 end
484 // -- Cop0 ------------------------------------------------------
486 tagged MTC0 .it :
487 begin
488 case ( it.cop0dst )
489 5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc)));
490 5'd21 : cp0_tohost <= truncate(rf.rd1(it.rsrc));
491 default :
492 $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" );
493 endcase
494 wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be.
495 end
497 //this is host stuff?
498 tagged MFC0 .it :
499 begin
500 case ( it.cop0src )
501 // not actually an ALU instruction but don't have the format otherwise
502 5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) });
503 5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost });
504 5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost });
505 default :
506 $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" );
507 endcase
508 end
510 // -- Illegal ---------------------------------------------------
512 default :
513 $display( " RTL-ERROR : %m : Illegal instruction !" );
515 endcase
517 //evaluate branch prediction
518 Addr ppc = pcQ.first().qnxtpc; //predicted branch
519 if (ppc != newPC) //prediction wrong
520 begin
521 epoch <= pcQ.first().qepoch + 1;
522 bp.upd(instrpc, newPC); //update branch predictor
523 pcQ.clear();
524 pc <= newPC;
525 end
526 else
527 pcQ.deq();
529 if ( cp0_statsEn )
530 num_inst.incr();
532 endrule
534 rule writeback; // ( stage == Writeback );
535 traceTiny("mkProc", "writeback","W");
538 // get what to do off the writeback queue
539 wbQ.deq();
540 case (wbQ.first()) matches
541 tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res);
542 tagged WB_Load .regWr :
543 begin
544 dataRespQ.deq();
545 if (dataRespQ.first() matches tagged LoadResp .ld)
546 rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue? Duplicate?
547 end
548 tagged WB_Store : dataRespQ.deq();
549 tagged WB_Host .dat : noAction;
550 endcase
552 endrule
554 rule inc_num_cycles;
555 if ( cp0_statsEn )
556 num_cycles.incr();
557 endrule
559 (* conservative_implicit_conditions *)
560 rule handleCPUToHost;
561 let req <- server_stub.acceptRequest_ReadCPUToHost();
562 case (req)
563 0: server_stub.sendResponse_ReadCPUToHost(cp0_tohost);
564 1: server_stub.sendResponse_ReadCPUToHost(pc);
565 2: server_stub.sendResponse_ReadCPUToHost(zeroExtend(pack(stage)));
566 endcase
567 endrule
569 // for now, we don't do anything.
570 rule connectAudioReqResp;
571 $display("FIR copies a data");
572 outAudioFifo.enq(inAudioFifo.first);
573 outAudioFifo.deq;
574 endrule
576 //-----------------------------------------------------------
577 // Methods
579 interface Client imem_client;
580 interface Get request = toGet(instReqQ);
581 interface Put response = toPut(instRespQ);
582 endinterface
584 interface Client dmem_client;
585 interface Get request = toGet(dataReqQ);
586 interface Put response = toPut(dataRespQ);
587 endinterface
589 interface Get statsEn_get = toGet(asReg(cp0_statsEn));
591 interface CPUToHost tohost;
592 method Bit#(32) cpuToHost(int req);
593 return (case (req)
594 0: cp0_tohost;
595 1: pc;
596 2: zeroExtend(pack(stage));
597 endcase);
598 endmethod
599 endinterface
601 interface Audio audio;
602 interface audioSampleInput = fifoToPut(inAudioFifo);
603 interface audioSampleOutput = fifoToGet(outAudioFifo);
604 endinterface
607 endmodule