replace defined_parameters with instance_defines
[shakti-peripherals.git] / src / uncore / debug / DebugModule.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package DebugModule;
15 /*====== Package imports === */
16 import FIFO::*;
17 import FIFOF::*;
18 import SpecialFIFOs::*;
19 import Semi_FIFOF::* ;
20 import GetPut::*;
21 import ClientServer::*;
22 import Vector::*;
23 import BUtils::*;
24 import ConfigReg::*;
25 import DReg::*;
26 /*========================== */
27 /*=== Project imports === */
28 import ConcatReg::*;
29 import AXI4_Types::*;
30 import AXI4_Fabric::*;
31 `include "defines.bsv"
32 `include "instance_defines.bsv"
33 import defined_types::*;
34 import core :: *;
35 /*========================= */
36
37 function Reg#(t) readOnlyReg(t r);
38 return (interface Reg;
39 method t _read = r;
40 method Action _write(t x) = noAction;
41 endinterface);
42 endfunction
43 interface Ifc_DebugModule;
44 method Action set_external_interrupt(Tuple2#(Bool,Bool) i);
45 method Action request_from_dtm(Bit#(40) requestfrmDTM);
46 method ActionValue#(Bit#(34)) response_to_dtm;
47 interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) debug_master;
48 interface AXI4_Slave_IFC#(`PADDR, `Reg_width, `USERSPACE) debug_slave;
49 /*======= Core related interfaces ====== */
50 interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) imem_master;
51 interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) dmem_master;
52 (*always_ready,always_enabled*)
53 method Action boot_sequence(Bit#(1) bootseq);
54 `ifdef CLINT
55 method Action clint_msip(Bit#(1) intrpt);
56 method Action clint_mtip(Bit#(1) intrpt);
57 method Action clint_mtime(Bit#(`Reg_width) c_mtime);
58 `endif
59 /*===========================================*/
60 endinterface
61
62 // this function is used to generate a resume request only when written by the
63 // debugger
64 function Reg#(Bit#(1)) condwriteSideEffect(Reg#(Bit#(1)) r, Action a);
65 return (interface Reg;
66 method Bit#(1) _read = r._read;
67 method Action _write(Bit#(1) x);
68 r._write(x);
69 if(x==1)
70 a;
71 endmethod
72 endinterface);
73 endfunction
74
75 (*synthesize*)
76 module mkDebugModule#(Bit#(`VADDR) reset_vector)(Ifc_DebugModule);
77 // Instantiating the Core
78 Ifc_core_AXI4 c64 <-mkcore_AXI4(reset_vector);
79 // Instantiating the AXI4 Master
80 AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) master_xactor <- mkAXI4_Master_Xactor;
81 AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) slave_xactor <- mkAXI4_Slave_Xactor;
82
83 /*========= FIFOs to communicate with the DTM==== */
84 FIFOF#(Bit#(34)) response_to_DTM <-mkFIFOF();
85 /*================================================ */
86
87 /*======= HART INFO REGISTERS =========== */
88 Reg#(Bit#(4)) nscratch =readOnlyReg(4'd2);
89 Reg#(Bit#(1)) dataaccess = readOnlyReg(1'b1);
90 Reg#(Bit#(4)) datasize = readOnlyReg(4'd12);
91 Reg#(Bit#(12)) dataaddr = readOnlyReg(12'h4c);
92 Reg#(Bit#(32)) hart_info =concatReg6(readOnlyReg(8'b0),
93 nscratch,readOnlyReg(3'b0),dataaccess,datasize,dataaddr);
94 /*======================================== */
95 //Registers from debug spec .13 start here
96 /*========= DM Control Registers ======== */
97 Reg#(Bit#(1)) haltreq<-mkReg(0);
98 Reg#(Bool) wr_gen_haltreq<-mkDReg(False);
99 Reg#(Bit#(1)) rg_haltreq=condwriteSideEffect(haltreq,wr_gen_haltreq._write(True));
100 Reg#(Bit#(1)) resume<-mkReg(0);
101 Reg#(Bool) wr_gen_resumereq<-mkDReg(False);
102 Reg#(Bit#(1)) rg_resumereq=condwriteSideEffect(resume,wr_gen_resumereq._write(True));
103 Reg#(Bit#(1)) rg_hartreset<-mkReg(0);
104 Reg#(Bit#(1)) rg_reset<-mkReg(0);
105 Reg#(Bit#(1)) rg_dmactive<-mkReg(1'b0);
106 Reg#(Bit#(10)) rg_hartsel<-mkReg(0);
107 Reg#(Bit#(32)) dm_control =concatReg9(rg_haltreq,rg_resumereq,
108 rg_hartreset,readOnlyReg(2'b0),readOnlyReg(1'b0),rg_hartsel,
109 readOnlyReg(14'b0),rg_reset,rg_dmactive);
110 /*======================================== */
111
112 /*====== DM STATUS REGISTERS ========== */
113 Reg#(Bit#(1)) rg_resumeack[2]<-mkCReg(2,0); // This is the Resume ACK
114 Reg#(Bit#(1)) rg_unavailable<-mkReg(0);
115 Reg#(Bit#(1)) rg_running <-mkReg(0);
116 Reg#(Bit#(1)) rg_halted<-mkReg(0);
117 ConfigReg#(Bit#(1)) rg_nonexistent<-mkConfigReg(0);
118 Reg#(Bit#(32)) dm_status =concatReg12(readOnlyReg(14'd0),
119 readOnlyReg(rg_resumeack[1]),readOnlyReg(rg_resumeack[1]),
120 readOnlyReg(rg_nonexistent),readOnlyReg(rg_nonexistent), readOnlyReg(rg_unavailable),readOnlyReg(rg_unavailable),
121 readOnlyReg(rg_running), readOnlyReg(rg_running),
122 readOnlyReg(rg_halted), readOnlyReg(rg_halted),
123 readOnlyReg(8'b10000010)); // TODO Make the 4th bit if using Configstring
124 /*======================================== */
125
126 /*== ABSTRACT REGISTERS === */
127 Reg#(Bit#(1)) rg_busy[3]<-mkCReg(3,0);
128 Reg#(Bit#(3)) rg_cmderr<-mkReg(0);
129 Reg#(Bit#(32)) abstract_Control_And_Status=concatReg8(readOnlyReg(3'b0),
130 readOnlyReg(5'd16),readOnlyReg(11'b0),
131 readOnlyReg(rg_busy[2]),readOnlyReg(1'b0),rg_cmderr,
132 readOnlyReg(3'b0),readOnlyReg(5'd12));
133
134 Reg#(Bit#(8)) rg_cmdtype <-mkReg(0);
135 Reg#(Bit#(24)) rg_control<-mkReg(0);
136 Reg#(Bit#(32)) abstract_Commands =concatReg2(rg_cmdtype,rg_control); //
137
138 Reg#(Bit#(16)) rg_autoexecprogbuf<-mkReg(0);
139 Reg#(Bit#(12)) rg_autoexecdata<-mkReg(0);
140 Reg#(Bit#(32)) abstract_Command_Autoexe =concatReg3(rg_autoexecprogbuf,readOnlyReg(4'b0),rg_autoexecdata) ;
141 Vector#(12,Array#(Reg#(Bit #(32)))) abstract_Data <- replicateM(mkCReg(2,0));
142 /*======================================== */
143
144
145 //Reg#(Bit#(32)) configuration_String_Addr_0<-mkReg (0) ; // TODO need to fiure this out
146 //Reg#(Bit#(32)) configuration_String_Addr_1<-mkReg (0) ;
147 //Reg#(Bit#(32)) configuration_String_Addr_2<-mkReg (0) ;
148 //Reg#(Bit#(32)) configuration_String_Addr_3<-mkReg (0) ;
149 //Reg#(Bit#(32)) serial_Control_And_Status <-mkReg (0) ;
150 //Reg#(Bit#(64)) serial_Data <-mkReg(0) ;
151 /*======= System Bus Access Registers ======= */
152 Reg#(Bit#(3)) rg_sberror<-mkReg(0);
153 Reg#(Bit#(1)) rg_sbautoread<-mkReg(0);
154 Reg#(Bit#(1)) rg_sbautoincrement<-mkReg(0);
155 Reg#(Bit#(3)) rg_sbaccess<-mkReg(0);
156 Reg#(Bit#(1)) rg_sbsingleread[2]<-mkCReg(2,0);
157 Reg#(Bit#(32)) bus_ctrlstatus=concatReg8(readOnlyReg(11'b0),
158 rg_sbsingleread[1],rg_sbaccess,
159 rg_sbautoincrement,rg_sbautoread,
160 rg_sberror,readOnlyReg(7'h40),
161 readOnlyReg(5'b01111));
162
163 Reg#(Bit#(32)) busAddr0[2] <- mkCReg(2,0) ;
164 Reg#(Bit#(32)) busData0[2] <- mkCReg(2,0) ;
165 Reg#(Bit#(32)) busData1[2] <- mkCReg(2,0) ;
166 /*======================================== */
167 Vector#(16,Array#(Reg#(Bit #(32) ))) program_Buffer <- replicateM(mkCReg(2,0)) ;
168
169 //not in spec , internally maintained for write
170 Reg#(Bool) write_flag[2] <- mkCReg(2,False) ;
171 Reg#(Bool) reset_status <-mkReg(True) ; // not in spec internally maintained for reset
172 Reg#(Bit#(32)) instruction0<-mkReg('h0000100f); // 0x0000100f fence.i
173 Reg#(Bit#(32)) instruction1<-mkReg('h00000013); // 0x00000013 nop (addi x0,x0,0)
174 Reg#(Bit#(32)) instruction2<-mkReg('hffdff06f); // 0xffdff06f jump to nop
175 Reg#(Bit#(32)) instruction3<-mkReg('h0040006f); // jump to progbuffer
176 Reg#(Bool) prog_ebreak_read<-mkReg(False);
177 Reg#(Bool) perform_reg_access[2] <-mkCReg(2,False);
178 Reg#(Bool) start_program_exec[3] <-mkCReg(3,False);
179 // 0 0 0 0100 0 0 0000 0110 1111
180 rule generate_nonexistent;
181 rg_nonexistent<=rg_hartsel==0?0:1;
182 endrule
183 rule rl_rd_respond;
184 // Get the wr request
185 let ar<- pop_o(slave_xactor.o_rd_addr);
186 AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata: ? ,rlast:True,ruser:0,rid:ar.arid};
187 `ifdef verbose
188 $display($time,"\tDEBUG:Address:%h size: %d",ar.araddr,ar.arsize);
189 $display($time,"\tDEBUG:Abstract Command: %h,%h,%h,start_program_exec %h",ar.araddr,rg_control[18] ,rg_busy[1],start_program_exec[0]);
190 `endif
191 if(ar.araddr>= (`DebugBase + 'h4c) && ar.araddr<=`DebugEnd)begin
192 Bit#(4) index=truncate((ar.araddr-'h4c)>>2);
193 `ifdef verbose $display($time,"\tDEBUG: Reading abstract data %d",index); `endif
194 if(ar.arsize==3)begin
195 r.rdata={abstract_Data[index+1][0],abstract_Data[index][0]};
196 end
197 else if(ar.arsize==2)begin
198 r.rdata=duplicate(abstract_Data[index][0]);
199 end
200 else
201 r.rresp=AXI4_SLVERR;
202 end
203 else if(ar.araddr>= (`DebugBase + 12) && ar.araddr<= `DebugBase+'h48)
204 begin
205 let index=(ar.araddr[5:2]-3);
206 `ifdef verbose $display($time,"\tDEBUG: Reading program buffer %d",index); `endif
207 Bit#(`Reg_width) data0={program_Buffer[index+1][0],program_Buffer[index][0]};
208 if(ar.arsize==3)begin
209 r.rdata={program_Buffer[index+1][0],program_Buffer[index][0]};
210 end
211 else if(ar.arsize==2)begin // 32 bit
212 r.rdata=duplicate(program_Buffer[index][0]);
213 end
214 else if (ar.arsize=='d1)begin // half_word
215 if(ar.araddr[`byte_offset:0] ==0)
216 r.rdata = duplicate(data0[15:0]);
217 else if(ar.araddr[`byte_offset:0] ==2)
218 r.rdata = duplicate(data0[31:16]);
219 `ifdef RV64
220 else if(ar.araddr[`byte_offset:0] ==4)
221 r.rdata = duplicate(data0[47:32]);
222 else if(ar.araddr[`byte_offset:0] ==6)
223 r.rdata = duplicate(data0[63:48]);
224 `endif
225 end
226 else if (ar.arsize=='d0) begin// one byte
227 if(ar.araddr[`byte_offset:0] ==0)
228 r.rdata = duplicate(data0[7:0]);
229 else if(ar.araddr[`byte_offset:0] ==1)
230 r.rdata = duplicate(data0[15:8]);
231 else if(ar.araddr[`byte_offset:0] ==2)
232 r.rdata = duplicate(data0[23:16]);
233 else if(ar.araddr[`byte_offset:0] ==3)
234 r.rdata = duplicate(data0[31:24]);
235 `ifdef RV64
236 else if(ar.araddr[`byte_offset:0] ==4)
237 r.rdata = duplicate(data0[39:32]);
238 else if(ar.araddr[`byte_offset:0] ==5)
239 r.rdata = duplicate(data0[47:40]);
240 else if(ar.araddr[`byte_offset:0] ==6)
241 r.rdata = duplicate(data0[55:48]);
242 else if(ar.araddr[`byte_offset:0] ==7)
243 r.rdata = duplicate(data0[63:56]);
244 `endif
245 end
246 if((program_Buffer[index][0][14:12]==`EBREAK_f3 && program_Buffer[index][0][6:2]==`CSR_op))
247 begin
248 start_program_exec[0]<=False;
249 `ifdef verbose $display($time,"\tDEBUG: EBREAK encountered"); `endif
250 end
251 end
252 else if(ar.araddr==`DebugBase && ar.arsize==2)
253 r.rdata=duplicate(instruction0);
254 else if(ar.araddr==`DebugBase+4 && ar.arsize==2)
255 r.rdata=duplicate(instruction1);
256 else if(ar.araddr==`DebugBase+8 && rg_control[18] == 1 && start_program_exec[0]) // postexec and busy
257 begin
258 r.rdata=duplicate(instruction3);
259 `ifdef verbose $display($time,"\tDEBUG :Redirecting to program buffer"); `endif
260 end
261 else if(ar.araddr==`DebugBase+8 && ar.arsize==2)begin
262 r.rdata=duplicate(instruction2);
263 rg_busy[1]<=0;
264 end
265 else
266 r.rresp=AXI4_SLVERR;
267 `ifdef verbose $display($time,"\tDEBUG: Reading Address:%h Data: %h",ar.araddr,r.rdata); `endif
268 slave_xactor.i_rd_data.enq(r);
269 endrule
270
271 rule rl_wr_response(!perform_reg_access[0]);
272 let aw <- pop_o (slave_xactor.o_wr_addr);
273 let w <- pop_o (slave_xactor.o_wr_data);
274 let b = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: aw.awuser, bid:aw.awid};
275 if(aw.awaddr>= (`DebugBase + 'h4c) && aw.awaddr<=`DebugEnd)begin
276 Bit#(4) index=truncate((aw.awaddr-'h4c)>>2);
277 if(aw.awsize==3)begin
278 abstract_Data[index+1][0]<=w.wdata[63:32];
279 abstract_Data[index][0]<=w.wdata[31:0];
280 end
281 else if(aw.awsize==2)begin
282 if(w.wstrb=='hf0)
283 abstract_Data[index+1][0]<=w.wdata[63:32];
284 else if(w.wstrb=='h0f)
285 abstract_Data[index][0]<=w.wdata[31:0];
286 end
287 else
288 b.bresp=AXI4_SLVERR;
289 end
290 else if(aw.awaddr>= (`DebugBase + 12) && aw.awaddr<= (`DebugBase+'h48))
291 begin
292 //let index=(aw.awaddr[7:0]-8)>>2;
293 let index=(aw.awaddr[5:2]-3);
294 if(w.wstrb=='hf0)
295 program_Buffer[index+1][0]<=w.wdata[63:32];
296 else if(w.wstrb=='h0f)
297 program_Buffer[index][0]<=w.wdata[31:0];
298 else if(w.wstrb=='hff)begin
299 program_Buffer[index][0]<=w.wdata[31:0];
300 program_Buffer[index+1][0]<=w.wdata[63:32];
301 end
302 end
303 else
304 b.bresp=AXI4_SLVERR;
305 slave_xactor.i_wr_resp.enq (b);
306 endrule
307
308
309 (*conflict_free = "access_register_or_pc,access_csrs"*)
310
311 /*=== Rules to halt the CPU === */
312 rule halt_request(wr_gen_haltreq && rg_halted == 0);
313 `ifdef verbose $display($time,"\tDEBUG: Requesting Halt"); `endif
314 c64.stop;
315 endrule
316
317 `ifdef verbose
318 rule display_Stuff;
319 `ifdef verbose $display($time,"\tDEBUG: HALT: %b",rg_halted); `endif
320 endrule
321 `endif
322
323 rule halt_status_of_cpu;
324 rg_halted <= pack(c64.halted) ;
325 endrule
326
327 rule resume_status(!wr_gen_resumereq);
328 if(resume==1 && !c64.halted)
329 rg_resumeack[0] <= 1;
330 endrule
331
332 rule resume_request(wr_gen_resumereq);
333 `ifdef verbose $display($time,"\tDEBUG: Requesting Resume\n"); `endif
334 // insert set for resume request set to zero here
335 rg_resumeack[0]<= 1'b0; // assert low on request
336 c64.run_continue;
337 endrule
338
339
340 rule reset(rg_hartreset == 1 && reset_status);
341 c64.reset;
342 `ifdef verbose $display($time,"\tDEBUG: Requesting Reset"); `endif
343 endrule
344
345 rule rst_status;
346 reset_status <= c64.reset_complete ;
347 endrule
348 rule access_register_or_pc(rg_halted == 1 && perform_reg_access[0] && rg_control[12]==1);
349 `ifdef verbose $display($time,"\tDEBUG: Access CONTROL: %h rg_halted: %b REGISTER NO.: %h",rg_control,rg_halted,abstract_Commands[15:0]); `endif
350 if(rg_control[16] == 0 && rg_control[17] == 1)// READ Operation
351 begin
352 `ifdef verbose $display($time,"\tREAD REGISTER OPERATION "); `endif
353 Bit#(`Reg_width) read_data =0;
354 if(rg_control[5] ==0)
355 begin
356 read_data = c64.read_igpr(rg_control[4:0]) ;
357 `ifdef verbose $display($time,"\tReading IGPR %d val: %h",rg_control[4:0],read_data); `endif
358 end
359 `ifdef spfpu
360 else
361 begin
362 read_data = c64.read_fgpr(rg_control[4:0]) ;
363 `ifdef verbose $display($time,"\tReading FGPR %d val: %h",rg_control[4:0],read_data); `endif
364 end
365 `endif
366 if(rg_control[22:20] == 2)begin
367 abstract_Data[0][0] <= read_data[31:0] ;
368 end
369 else if(rg_control[22:20] == 3)begin
370 abstract_Data[0][0] <= read_data[31:0] ;
371 abstract_Data[1][0] <= read_data[63:32] ;
372 end
373 end
374 else if(rg_control[16] == 1 && rg_control[17] == 1) // Write operation
375 begin
376 Bit#(64) write_data = 0 ;
377 if(rg_control[22:20] == 2)begin
378 write_data = zeroExtend(abstract_Data[0][0]) ;
379 end
380 else if(rg_control[22:20] == 3)begin
381 write_data[31:0] = abstract_Data[0][0] ;
382 write_data[63:32] = abstract_Data[1][0] ;
383 end
384
385 if(rg_control[5] == 'h0)
386 begin
387 c64.write_igpr(rg_control[4:0],truncate(write_data) ) ;
388 `ifdef verbose $display($time,"\tWriting IGPR %d val: %h",rg_control[4:0],write_data); `endif
389 end
390 `ifdef spfpu
391 else
392 begin
393 c64.write_fgpr(rg_control[4:0],truncate(write_data)) ;
394 `ifdef verbose $display($time,"\tWriting FGPR %d val: %h",rg_control[4:0],write_data); `endif
395 end
396 `endif
397 end
398 perform_reg_access[0]<=False;
399 if(rg_control[18] == 1)begin
400 start_program_exec[1] <= True ; //clear busy
401 `ifdef verbose $display("DEBUG: De-assert Abstract Busy\n"); `endif
402 end
403 else
404 rg_busy[1]<=0;
405 endrule
406
407 rule access_csrs(rg_halted==1 && perform_reg_access[0] && rg_control[17]==1 && rg_control[12]==0);
408 Bit#(`Reg_width) read_data =0;
409 if(rg_control[16]==0)begin// READ Operation
410 let x<-c64.rw_csr(rg_control[11:0],False,?);
411 read_data=x;
412 `ifdef verbose $display($time,"\tDEBUG: READING CSR : address : %h data: %h",rg_control[11:0],read_data); `endif
413 if(rg_control[22:20] == 2)begin
414 abstract_Data[0][0] <= read_data[31:0] ;
415 end
416 else if(rg_control[22:20] == 3)begin
417 abstract_Data[0][0] <= read_data[31:0] ;
418 abstract_Data[1][0] <= read_data[63:32] ;
419 end
420 end
421 else begin// WRITE Operation
422 Bit#(64) write_data = 0 ;
423 if(rg_control[22:20] == 2)begin
424 write_data = zeroExtend(abstract_Data[0][0]) ;
425 end
426 else if(rg_control[22:20] == 3)begin
427 write_data[31:0] = abstract_Data[0][0] ;
428 write_data[63:32] = abstract_Data[1][0] ;
429 end
430 `ifdef verbose $display($time,"\tDEBUG: WRITING CSR : address : %h data: %h",rg_control[11:0],write_data); `endif
431 let x<-c64.rw_csr(rg_control[11:0],True,write_data);
432 end
433 perform_reg_access[0] <=False; //clear busy
434 if(rg_control[18] == 1)begin
435 start_program_exec[1] <= True ; //clear busy
436 `ifdef verbose $display("DEBUG: De-assert Abstract Busy\n"); `endif
437 end
438 else
439 rg_busy[1]<=0;
440 `ifdef verbose $display($time,"\tDEBUG: De-assert Abstract Busy\n"); `endif
441 endrule
442
443
444 /*==================================== */
445
446 rule access_memory_request (rg_sbsingleread[0]==1 || write_flag[0] == True);
447 Bit #(32) address ;
448 address[31:0]=busAddr0[0];
449
450 Bit#(8) size =0 ; // size in bytes
451 case (rg_sbaccess)
452 0: size = 1 ;
453 1: size = 2;
454 2: size = 4 ;
455 3: size = 8 ;
456 endcase
457
458 if(rg_sbsingleread[0] == 1)
459 begin
460 rg_sbsingleread[0]<=0;
461 let read_request = AXI4_Rd_Addr {araddr:truncate(address) , aruser: 0, arlen: 0, arsize:rg_sbaccess, arburst: 'b01, arid:'d2}; // arburst: 00-FIXED 01-INCR 10-WRAP
462 master_xactor.i_rd_addr.enq(read_request);
463 end
464
465 else
466 begin
467 write_flag[0] <= False ;
468 Bit#(64) write_data=0;
469 if(size == 8)
470 begin
471 write_data[31:0] = busData0[0] ;
472 write_data[63:32] = busData1[0] ;
473 end
474 else
475 begin
476 if (size==4)
477 begin
478 write_data[31:0] = busData0[0] ; write_data[63:32]=busData0[0];
479 end
480 if (size==2)
481 begin
482 write_data[15:0] = busData0[0][15:0];write_data[31:16] = busData0[0][15:0];write_data[47:32] = busData0[0][15:0];write_data[63:48] = busData0[0][15:0];
483 end
484 if (size==1)
485 begin
486 write_data[7:0] = busData0[0][7:0];write_data[15:8] = busData0[0][7:0];write_data[23:16] = busData0[0][7:0];write_data[31:24] = busData0[0][7:0];
487 write_data[39:32] = busData0[0][7:0];write_data[47:40] = busData0[0][7:0];write_data[55:48] = busData0[0][7:0];write_data[63:56] = busData0[0][7:0];
488 end
489 end
490 Bit#(8) write_strobe=size==1?8'b1:size==2?8'b11:size==4?8'hf:8'hff;
491 if(size!=8)begin // 8-bit write;
492 write_strobe=write_strobe<<(address[`byte_offset:0]);
493 end
494 address[2:0]=0;
495
496 `ifdef verbose $display("Debug : Memory Write: Data written : %d Address : %d Write_Strobe : %b",write_data[31:0],address,write_strobe); `endif
497
498 let request_data = AXI4_Wr_Data {wdata: write_data , wstrb: write_strobe, wlast:True, wid:'d2};
499 let request_address = AXI4_Wr_Addr {awaddr: address, awuser:0, awlen: 0, awsize: rg_sbaccess, awburst: 'b01, awid:'d2}; // arburst: 00-FIXED 01-INCR 10-WRAP
500 master_xactor.i_wr_addr.enq(request_address) ;
501 master_xactor.i_wr_data.enq(request_data) ;
502
503 end
504
505 if(rg_sbautoincrement == 1)begin
506 Bit #(32) address1 ;
507 address1[31:0]=busAddr0[0];
508 address1 = address1 + zeroExtend(size) ;
509 busAddr0[0] <= address1[31:0] ;
510 end
511 endrule
512
513 rule read_memory_response ;
514 let response<-pop_o(master_xactor.o_rd_data);
515 if (response.rresp==AXI4_OKAY && response.rid=='d2)
516 begin
517 Bit #(64) resp=zeroExtend (response.rdata);
518 busData0[0]<=resp[31:0] ;
519 busData1[0]<=resp[63:32] ;
520 end
521 endrule
522
523 rule write_memory_response ;
524 let response <- pop_o(master_xactor.o_wr_resp) ;
525 if(response.bresp == AXI4_OKAY && response.bid=='d2)
526 begin
527 `ifdef verbose $display("Write Done Successfully"); `endif
528 end
529 endrule
530
531
532
533
534
535 /*==== This rule will interact with the external DTM and perform Read/Write to the DM Registers === */
536 //method ActionValue#(DTMResponse) toDTM(DTMRequest req)if(rg_busy[0]==0);
537 method Action request_from_dtm(Bit#(40) requestfrmDTM);
538 Bit#(2) op=requestfrmDTM[1:0];
539 Bit#(32) data=requestfrmDTM[33:2];
540 Bit#(6) address=requestfrmDTM[39:34];
541 `ifdef verbose $display($time,"\tDEBUG: Receiving Request from DTM:\t op: %d data: %h address: %h",op,data,address); `endif
542 Bit#(34) response='h0;
543 if(op==2)begin // WRITE OPERATION
544 case (address)
545 `DMCONTROL:
546 begin
547 if(data[30] == 1 && data[31] == 1)begin
548 response[1:0] = 2 ;
549 end
550 else begin
551 dm_control<=data;
552 end
553 end
554 `DMSTATUS : dm_status<=data;
555 `HARTINFO : hart_info<=data;
556 `ABSTRACTCNTRL: abstract_Control_And_Status<=data;
557 `ABSTRACTCMD :begin if(rg_busy[2]==1 || start_program_exec[2]) rg_cmderr<=1; else begin abstract_Commands<=data; rg_busy[2]<=1; perform_reg_access[1]<=True; end end
558 `ABSTRACTCMDAUTO:begin abstract_Command_Autoexe<=data; end// ; rg_busy[0] <= 1 ; end
559 `BUSCONTROL: bus_ctrlstatus<=data;
560 `BUSADDRESS0:busAddr0[1]<=data;
561 `BUSDATA0 :begin busData0[1]<=data; write_flag[1] <= True ; end
562 `BUSDATA1 :busData1[1]<=data;
563 default: begin
564 if(address>=`ABSTRACTDATASTART && address<=`ABSTRACTDATAEND)
565 begin
566 `ifdef verbose $display($time,"DEBUG: Autoexec Write Detected"); `endif
567 abstract_Data[address[3:0]-`ABSTRACTDATASTART][1]<=data;
568 if(abstract_Command_Autoexe[address[3:0]-`ABSTRACTDATASTART] == 1)
569 begin
570 `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on write to abstract data "); `endif
571 perform_reg_access[1] <=True;
572 end
573 end
574 else if(address>=`PBSTART && address<=`PBEND)
575 begin
576 `ifdef verbose $display($time,"\tDEBUG: Autoexec Write Detected to PG index: %h",address[3:0]); `endif
577 program_Buffer[address[3:0]][1]<=truncate(data);
578 if(rg_autoexecprogbuf[address[5:0]-`PBSTART + 16] == 1)
579 begin
580 `ifdef verbose $display($time,"\tDEBUG: Autoexecuting command based on write to program buffer"); `endif
581 perform_reg_access[1] <=True;
582 end
583 end
584 else
585 response[1:0]=2;
586 end
587 endcase
588 end
589 else if(op==1) begin // READ OPERATION
590 case (address)
591 `DMCONTROL : response[33:2]=dm_control;
592 `DMSTATUS : response[33:2]=dm_status;
593 `HARTINFO : response[33:2]=hart_info;
594 `ABSTRACTCNTRL: response[33:2]=abstract_Control_And_Status;
595 `ABSTRACTCMD : response[33:2]=abstract_Commands;
596 `ABSTRACTCMDAUTO:response[33:2]=abstract_Command_Autoexe;
597 `BUSCONTROL :response[33:2]=bus_ctrlstatus;
598 `BUSADDRESS0 :response[33:2]=busAddr0[1];
599 `BUSDATA0 :begin
600 response[33:2]=busData0[1];
601 if(rg_sbautoread == 1)begin
602 rg_sbsingleread[1] <= 1;
603 end
604 end
605 `BUSDATA1 :response[33:2]=busData1[1];
606 default: begin
607 if(address>=`ABSTRACTDATASTART && address<=`ABSTRACTDATAEND)
608 begin
609 `ifdef verbose $display($time,"DEBUG: Autoexec Read Detected"); `endif
610 response[33:2]=zeroExtend(abstract_Data[address[3:0]-`ABSTRACTDATASTART][1]);
611 if(abstract_Command_Autoexe[address[3:0]-`ABSTRACTDATASTART] == 1)
612 begin
613 `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on read in abstract data "); `endif
614 perform_reg_access[1] <=True;
615 end
616 end
617 else if(address>=`PBSTART && address<=`PBEND)
618 begin
619 `ifdef verbose $display($time,"DEBUG1: Autoexec Read Detected"); `endif
620 response[33:2]=zeroExtend(program_Buffer[address[3:0]][1]);
621 if(abstract_Command_Autoexe[address[5:0]-`PBSTART + 16] == 1)
622 begin
623 `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on read in program buffer"); `endif
624 perform_reg_access[1] <=True;
625 end
626 end
627 else
628 response[1:0]=2;
629 end
630 endcase
631 end
632 `ifdef verbose $display($time,"\tDebug: Responding with data: %h op: %d",response[33:2],response[1:0]); `endif
633 response_to_DTM.enq(response);
634 endmethod
635 method ActionValue#(Bit#(34)) response_to_dtm;
636 response_to_DTM.deq;
637 return response_to_DTM.first;
638 endmethod
639 /*====================================================================================================== */
640
641 interface imem_master=c64.imem_master;
642 interface dmem_master=c64.dmem_master;
643
644 interface debug_master=master_xactor.axi_side;
645 interface debug_slave =slave_xactor.axi_side;
646 method Action boot_sequence(Bit#(1) bootseq)=c64.boot_sequence(bootseq);
647 method Action set_external_interrupt(Tuple2#(Bool,Bool) i)=c64.set_external_interrupt(i);
648 `ifdef CLINT
649 method Action clint_msip(Bit#(1) intrpt)=c64.clint_msip(intrpt);
650 method Action clint_mtip(Bit#(1) intrpt)=c64.clint_mtip(intrpt);
651 method Action clint_mtime(Bit#(`Reg_width) c_mtime)=c64.clint_mtime(c_mtime);
652 `endif
653 endmodule
654 endpackage