2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
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.
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15 /*====== Package imports === */
18 import SpecialFIFOs::*;
19 import Semi_FIFOF::* ;
21 import ClientServer::*;
26 /*========================== */
27 /*=== Project imports === */
30 import AXI4_Fabric::*;
31 `include "defines.bsv"
32 `include "defined_parameters.bsv"
33 import defined_types::*;
35 /*========================= */
37 function Reg#(t) readOnlyReg(t r);
38 return (interface Reg;
40 method Action _write(t x) = noAction;
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);
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);
59 /*===========================================*/
62 // this function is used to generate a resume request only when written by the
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);
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;
83 /*========= FIFOs to communicate with the DTM==== */
84 FIFOF#(Bit#(34)) response_to_DTM <-mkFIFOF();
85 /*================================================ */
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 /*======================================== */
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 /*======================================== */
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));
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); //
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 /*======================================== */
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));
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)) ;
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;
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};
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]);
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]};
197 else if(ar.arsize==2)begin
198 r.rdata=duplicate(abstract_Data[index][0]);
203 else if(ar.araddr>= (`DebugBase + 12) && ar.araddr<= `DebugBase+'h48)
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]};
211 else if(ar.arsize==2)begin // 32 bit
212 r.rdata=duplicate(program_Buffer[index][0]);
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]);
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]);
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]);
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]);
246 if((program_Buffer[index][0][14:12]==`EBREAK_f3 && program_Buffer[index][0][6:2]==`CSR_op))
248 start_program_exec[0]<=False;
249 `ifdef verbose $display($time,"\tDEBUG: EBREAK encountered"); `endif
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
258 r.rdata=duplicate(instruction3);
259 `ifdef verbose $display($time,"\tDEBUG :Redirecting to program buffer"); `endif
261 else if(ar.araddr==`DebugBase+8 && ar.arsize==2)begin
262 r.rdata=duplicate(instruction2);
267 `ifdef verbose $display($time,"\tDEBUG: Reading Address:%h Data: %h",ar.araddr,r.rdata); `endif
268 slave_xactor.i_rd_data.enq(r);
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];
281 else if(aw.awsize==2)begin
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];
290 else if(aw.awaddr>= (`DebugBase + 12) && aw.awaddr<= (`DebugBase+'h48))
292 //let index=(aw.awaddr[7:0]-8)>>2;
293 let index=(aw.awaddr[5:2]-3);
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];
305 slave_xactor.i_wr_resp.enq (b);
309 (*conflict_free = "access_register_or_pc,access_csrs"*)
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
319 `ifdef verbose $display($time,"\tDEBUG: HALT: %b",rg_halted); `endif
323 rule halt_status_of_cpu;
324 rg_halted <= pack(c64.halted) ;
327 rule resume_status(!wr_gen_resumereq);
328 if(resume==1 && !c64.halted)
329 rg_resumeack[0] <= 1;
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
340 rule reset(rg_hartreset == 1 && reset_status);
342 `ifdef verbose $display($time,"\tDEBUG: Requesting Reset"); `endif
346 reset_status <= c64.reset_complete ;
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
352 `ifdef verbose $display($time,"\tREAD REGISTER OPERATION "); `endif
353 Bit#(`Reg_width) read_data =0;
354 if(rg_control[5] ==0)
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
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
366 if(rg_control[22:20] == 2)begin
367 abstract_Data[0][0] <= read_data[31:0] ;
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] ;
374 else if(rg_control[16] == 1 && rg_control[17] == 1) // Write operation
376 Bit#(64) write_data = 0 ;
377 if(rg_control[22:20] == 2)begin
378 write_data = zeroExtend(abstract_Data[0][0]) ;
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] ;
385 if(rg_control[5] == 'h0)
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
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
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
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,?);
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] ;
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] ;
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]) ;
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] ;
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);
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
440 `ifdef verbose $display($time,"\tDEBUG: De-assert Abstract Busy\n"); `endif
444 /*==================================== */
446 rule access_memory_request (rg_sbsingleread[0]==1 || write_flag[0] == True);
448 address[31:0]=busAddr0[0];
450 Bit#(8) size =0 ; // size in bytes
458 if(rg_sbsingleread[0] == 1)
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);
467 write_flag[0] <= False ;
468 Bit#(64) write_data=0;
471 write_data[31:0] = busData0[0] ;
472 write_data[63:32] = busData1[0] ;
478 write_data[31:0] = busData0[0] ; write_data[63:32]=busData0[0];
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];
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];
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]);
496 `ifdef verbose $display("Debug : Memory Write: Data written : %d Address : %d Write_Strobe : %b",write_data[31:0],address,write_strobe); `endif
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) ;
505 if(rg_sbautoincrement == 1)begin
507 address1[31:0]=busAddr0[0];
508 address1 = address1 + zeroExtend(size) ;
509 busAddr0[0] <= address1[31:0] ;
513 rule read_memory_response ;
514 let response<-pop_o(master_xactor.o_rd_data);
515 if (response.rresp==AXI4_OKAY && response.rid=='d2)
517 Bit #(64) resp=zeroExtend (response.rdata);
518 busData0[0]<=resp[31:0] ;
519 busData1[0]<=resp[63:32] ;
523 rule write_memory_response ;
524 let response <- pop_o(master_xactor.o_wr_resp) ;
525 if(response.bresp == AXI4_OKAY && response.bid=='d2)
527 `ifdef verbose $display("Write Done Successfully"); `endif
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
547 if(data[30] == 1 && data[31] == 1)begin
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;
564 if(address>=`ABSTRACTDATASTART && address<=`ABSTRACTDATAEND)
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)
570 `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on write to abstract data "); `endif
571 perform_reg_access[1] <=True;
574 else if(address>=`PBSTART && address<=`PBEND)
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)
580 `ifdef verbose $display($time,"\tDEBUG: Autoexecuting command based on write to program buffer"); `endif
581 perform_reg_access[1] <=True;
589 else if(op==1) begin // READ OPERATION
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];
600 response[33:2]=busData0[1];
601 if(rg_sbautoread == 1)begin
602 rg_sbsingleread[1] <= 1;
605 `BUSDATA1 :response[33:2]=busData1[1];
607 if(address>=`ABSTRACTDATASTART && address<=`ABSTRACTDATAEND)
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)
613 `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on read in abstract data "); `endif
614 perform_reg_access[1] <=True;
617 else if(address>=`PBSTART && address<=`PBEND)
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)
623 `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on read in program buffer"); `endif
624 perform_reg_access[1] <=True;
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);
635 method ActionValue#(Bit#(34)) response_to_dtm;
637 return response_to_DTM.first;
639 /*====================================================================================================== */
641 interface imem_master=c64.imem_master;
642 interface dmem_master=c64.dmem_master;
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);
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);