📄 cpuside.v
字号:
dedsec = dedsec_bits({cacheline[127:32+16], source[7:0], cacheline[31+ 8:0]}); end 4'b0110 : begin cacheline[ 32+23: 32+16] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:32+24], source[7:0], cacheline[31+16:0]}); end 4'b0111 : begin cacheline[ 32+31: 32+24] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:32+32], source[7:0], cacheline[31+24:0]}); end 4'b1000 : begin cacheline[ 64+ 7: 64+ 0] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:64+ 8], source[7:0], cacheline[63+ 0:0]}); end 4'b1001 : begin cacheline[ 64+15: 64+ 8] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:64+16], source[7:0], cacheline[63+ 8:0]}); end 4'b1010 : begin cacheline[ 64+23: 64+16] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:64+24], source[7:0], cacheline[63+16:0]}); end 4'b1011 : begin cacheline[ 64+31: 64+24] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:64+32], source[7:0], cacheline[63+24:0]}); end 4'b1100 : begin cacheline[ 96+ 7: 96+ 0] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:96+ 8], source[7:0], cacheline[95+ 0:0]}); end 4'b1101 : begin cacheline[ 96+15: 96+ 8] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:96+16], source[7:0], cacheline[95+ 8:0]}); end 4'b1110 : begin cacheline[ 96+23: 96+16] = source[ 7: 0]; dedsec = dedsec_bits({cacheline[127:96+24], source[7:0], cacheline[95+16:0]}); end 4'b1111 : begin cacheline[ 96+31: 96+24] = source[ 7: 0]; dedsec = dedsec_bits({ source[7:0], cacheline[95+24:0]}); end endcase // case(address[3:2]) end endtask // input_byte // Use word index to output the appropriate word from the cacheline to D task output_word; input [127:0] cacheline; input [1:0] word; begin case (word) 2'b00 : Dout = cacheline[31:0]; 2'b01 : Dout = cacheline[63:32]; 2'b10 : Dout = cacheline[95:64]; 2'b11 : Dout = cacheline[127:96]; endcase // case(address[3:2]) end endtask // Use bytepos index to output the appropriate byte from the cacheline to D task output_byte; input [127:0] cacheline; input [3:0] bytepos; begin Dout[31:8] = 24'h000000; case (bytepos) 4'b0000 : Dout[7:0] = cacheline[ 0+ 7: 0+ 0]; 4'b0001 : Dout[7:0] = cacheline[ 0+15: 0+ 8]; 4'b0010 : Dout[7:0] = cacheline[ 0+23: 0+16]; 4'b0011 : Dout[7:0] = cacheline[ 0+31: 0+24]; 4'b0100 : Dout[7:0] = cacheline[ 32+ 7: 32+ 0]; 4'b0101 : Dout[7:0] = cacheline[ 32+15: 32+ 8]; 4'b0110 : Dout[7:0] = cacheline[ 32+23: 32+16]; 4'b0111 : Dout[7:0] = cacheline[ 32+31: 32+24]; 4'b1000 : Dout[7:0] = cacheline[ 64+ 7: 64+ 0]; 4'b1001 : Dout[7:0] = cacheline[ 64+15: 64+ 8]; 4'b1010 : Dout[7:0] = cacheline[ 64+23: 64+16]; 4'b1011 : Dout[7:0] = cacheline[ 64+31: 64+24]; 4'b1100 : Dout[7:0] = cacheline[ 96+ 7: 96+ 0]; 4'b1101 : Dout[7:0] = cacheline[ 96+15: 96+ 8]; 4'b1110 : Dout[7:0] = cacheline[ 96+23: 96+16]; 4'b1111 : Dout[7:0] = cacheline[ 96+31: 96+24]; endcase // case(address[3:2]) end endtask // Displace to victim cache task move_main_to_victim; input [31:0] address; // NB. Only upper bits of address are used // (for working out the cache line) begin `ifdef TALK $display("CPUside: Moving cache line b%b = d%d (address %h) to victim cache", main_cache_line(address), main_cache_line(address), address); `endif victim_cache[oldest_victim_line] <= @(posedge sysclk) main_cache[main_cache_line(address)]; // The victim tag is the main tag && offset victim_cache_tag[oldest_victim_line] <= @(posedge sysclk) { main_cache_tag[main_cache_line(address)], main_cache_line(address) }; victim_cache_dedsec[oldest_victim_line] <= @(posedge sysclk) main_cache_dedsec[main_cache_line(address)]; victim_cache_valid[oldest_victim_line] <= @(posedge sysclk) main_cache_valid[main_cache_line(address)]; // Move our FIFO onwards oldest_victim_line <= @(posedge sysclk) oldest_victim_line + 1; end endtask // Swap lines in the two caches task swap_caches; input [31:0] address; begin victim_cache_tag[victim_cache_line(address)] <= @(posedge sysclk) { main_cache_tag[main_cache_line(address)], main_cache_line(address) }; victim_cache[victim_cache_line(address)] <= @(posedge sysclk) main_cache[main_cache_line(address)]; victim_cache_dedsec[victim_cache_line(address)] <= @(posedge sysclk) main_cache_dedsec[main_cache_line(address)]; main_cache_tag[main_cache_line(address)] <= @(posedge sysclk) A[31:32-`MAIN_CACHE_TAG_BITS]; // *********** Check this line ************************* main_cache[main_cache_line(address)] <= @(posedge sysclk) victim_cache[victim_cache_line(address)]; main_cache_dedsec[main_cache_line(address)] <= @(posedge sysclk) victim_cache_dedsec[victim_cache_line(address)]; end endtask // Returns the bits used for indexing the main cache from the given address function [`MAIN_CACHE_LINE_BITS-1:0] main_cache_line; input [31:0] address; main_cache_line = address[`MAIN_CACHE_LINE_BIT_HIGH:`MAIN_CACHE_LINE_BIT_LOW]; endfunction // Returns the bits used for indexing the victim cache from the given address function [27:0] victim_cache_line; input [31:0] address; if (victim_cache_tag[0] == address[31:4]) victim_cache_line = 0; else if (victim_cache_tag[1] == address[31:4]) victim_cache_line = 1; else if (victim_cache_tag[2] == address[31:4]) victim_cache_line = 2; else //if (victim_cache_tag[3] == address[31:4]) victim_cache_line = 3; endfunction // Returns whether the given address has a match in the main cache function in_main_cache; input [31:0] address; in_main_cache = ( main_cache_tag[main_cache_line(address)] == address[`MAIN_CACHE_TAG_BIT_HIGH:`MAIN_CACHE_TAG_BIT_LOW] & main_cache_valid[main_cache_line(address)] & main_dedsec_result ); endfunction // Returns whether the given address has a match in the victim cache function in_victim_cache; input [31:0] address; in_victim_cache = ( ( ( ( victim_cache_tag[0] == address[31:4]) & victim_cache_valid[0] ) | ( (victim_cache_tag[1] == address[31:4]) & victim_cache_valid[1] ) | ( (victim_cache_tag[2] == address[31:4]) & victim_cache_valid[2] ) | ( (victim_cache_tag[3] == address[31:4]) & victim_cache_valid[3] ) ) & victim_dedsec_result ); endfunction // in_victim_cache // nWAIT assignment assign nWAIT = !cpu_busy; // D assignment assign D = Dout; // Initial setup initial begin present_cpu_state = `CPUSIDE_IDLE; for (i = 0; i < `MAIN_CACHE_LINES; i = i+1) main_cache_valid[i] = 0; for (i = 0; i < `VICTIM_CACHE_LINES; i = i+1) victim_cache_valid[i] = 0; oldest_victim_line = 0; end // Correct DEDSEC errors as they occur - main cache always begin @(posedge sysclk) #1; pass_dedsec(main_cache[main_cache_line(A)], main_cache_dedsec[main_cache_line(A)], main_dedsec_result ); end // always begin // Correct DEDSEC errors as they occur - victim cache always begin @(posedge sysclk) #1; pass_dedsec(victim_cache[victim_cache_line(A)], victim_cache_dedsec[victim_cache_line(A)], victim_dedsec_result ); end // always begin // CPU ASM always begin @(posedge sysclk) enter_new_cpu_state(`CPUSIDE_IDLE); cpu_busy = 0; if (! nMREQ) if (nRW) // Write / Store begin while (st_busy) begin cpu_busy = 1; @(posedge sysclk) enter_new_cpu_state(`CPUSIDE_WAIT); end // while (st_busy) if (in_main_cache(A)) if (MAS[1]) input_word(main_cache[main_cache_line(A)], A[3:2], D, main_cache_dedsec[main_cache_line(A)]); else input_byte(main_cache[main_cache_line(A)], A[3:0], D, main_cache_dedsec[main_cache_line(A)]); else if (in_victim_cache(A)) begin if (MAS[1]) input_word(victim_cache[victim_cache_line(A)], A[3:2], D, victim_cache_dedsec[victim_cache_line(A)]); else input_byte(victim_cache[victim_cache_line(A)], A[3:0], D, victim_cache_dedsec[victim_cache_line(A)]); end // if (in_victim_cache(A)) if (MAS[1]) begin // Memoryside needs this in a register write_buffer_data <= @(posedge sysclk) D; end else begin // Memoryside needs this in a register write_buffer_data <= @(posedge sysclk) {D[7:0], D[7:0], D[7:0], D[7:0]}; end // else: !if(MAS[1]) // Memoryside needs this in a register write_buffer_is_byte <= @(posedge sysclk) ! MAS[1]; // Memoryside needs the address in this clock cycle write_buffer_addr = A; Store_Trigger = 1; end else begin // (!nRW) = Read / Load `ifdef TALK $display("CPUside: Load start"); `endif if (in_main_cache(A)) begin `ifdef TALK $display("CPUside: Main cache hit"); `endif if (MAS[1]) output_word(main_cache[main_cache_line(A)], A[3:2]); else output_byte(main_cache[main_cache_line(A)], A[3:0]); end // if (in_main_cache(A)) else if (in_victim_cache(A)) begin `ifdef TALK $display("CPUside: Victim cache hit (will swap cache w. main)"); `endif if (MAS[1]) output_word(victim_cache[victim_cache_line(A)], A[3:2]); else output_byte(victim_cache[victim_cache_line(A)], A[3:0]); swap_caches(A); end // if (in_victim_cache) else begin if (main_cache_valid[main_cache_line(A)]) // Only moving it if the line is valid is a small optimisation // for the victim cache. // Probably not beneficial for a normal CPU, but will make a // difference in the small tests that will be run here! // Will also make debugging easier. // In other words, the above "if" should probably be removed, // but I'm leaving it in for now. move_main_to_victim(A); // Stall until Memoryside is ready while (st_busy) begin cpu_busy = 1; @(posedge sysclk) enter_new_cpu_state(`CPUSIDE_WAIT2); end // while (st_busy) // Memoryside now ready, so give it its next piece of work. Load_Trigger = 1; cpu_busy = 1; // Ensure that CPU waits... // Get data from Memoryside as it becomes ready while (ld_busy | (present_cpu_state != `CPUSIDE_LOADING)) begin @(posedge sysclk) enter_new_cpu_state(`CPUSIDE_LOADING); cpu_busy = 1; #2; if (load_from_mem_req) input_word(main_cache[main_cache_line(A)], load_from_mem_offset, load_from_mem_data, main_cache_dedsec[main_cache_line(A)]); end // while (ld_busy) @(posedge sysclk) enter_new_cpu_state(`CPUSIDE_LOADEND); // Calculate DEDSEC bits for the newly loaded cache line main_cache_dedsec[main_cache_line(A)] <= @(posedge sysclk) dedsec_bits(main_cache[main_cache_line(A)]); // Save the tag main_cache_tag[main_cache_line(A)] <= @(posedge sysclk) A[`MAIN_CACHE_TAG_BIT_HIGH:`MAIN_CACHE_TAG_BIT_LOW]; // Mark that this line is valid main_cache_valid[main_cache_line(A)] <= @(posedge sysclk) 1; $display ("%d: A=%h D=%h", $time, A, main_cache[main_cache_line(A)]); // Output to ARM Core if (MAS[1]) output_word(main_cache[main_cache_line(A)], A[3:2]); else output_byte(main_cache[main_cache_line(A)], A[3:0]); `ifdef TALK $display("CPUside: Load (from mem) result output (line=%h)", main_cache_line(A)); `endif end // else: !if(in_victim_cache) end // else: !if(nRW) end // always begin task enter_new_cpu_state; input [`CPUSIDE_NUM_STATE_BITS-1:0] this_state; begin #0 Dout = 32'hzzzzzzzz; #1 present_cpu_state = this_state; Load_Trigger = 0; Store_Trigger = 0; cpu_busy = 0; // Any more to be added? end endtask // enter_new_cpu_state endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -