Line 123... |
Line 123... |
//
|
//
|
// Internal wires and regs
|
// Internal wires and regs
|
//
|
//
|
reg [31:0] addr_r;
|
reg [31:0] addr_r;
|
reg [2:0] state;
|
reg [2:0] state;
|
reg [2:0] cnt;
|
reg [`OR1200_DCLS-1:0] cnt;
|
reg hitmiss_eval;
|
reg hitmiss_eval;
|
reg store;
|
reg store;
|
reg load;
|
reg load;
|
reg cache_inhibit;
|
reg cache_inhibit;
|
reg cache_miss;
|
reg cache_miss;
|
Line 148... |
Line 148... |
wire dcram_we_during_line_load;
|
wire dcram_we_during_line_load;
|
wire tagram_we_end_of_loadstore_loop;
|
wire tagram_we_end_of_loadstore_loop;
|
wire tagram_dirty_bit_set;
|
wire tagram_dirty_bit_set;
|
wire writethrough;
|
wire writethrough;
|
wire cache_inhibit_with_eval;
|
wire cache_inhibit_with_eval;
|
wire [1:0] next_addr_word;
|
wire [(`OR1200_DCLS-1)-2:0] next_addr_word;
|
|
|
//
|
//
|
// Cache inhibit
|
// Cache inhibit
|
//
|
//
|
|
|
Line 266... |
Line 266... |
assign dcram_di_sel = load;
|
assign dcram_di_sel = load;
|
// Data to external bus - always from IU except in case of bursting back
|
// Data to external bus - always from IU except in case of bursting back
|
// the line to memory. (1 selects DCRAM)
|
// the line to memory. (1 selects DCRAM)
|
assign biu_do_sel = (state == `OR1200_DCFSM_LOOP2) & store;
|
assign biu_do_sel = (state == `OR1200_DCFSM_LOOP2) & store;
|
|
|
// 2-bit wire for calculating next word of burst write
|
// 3-bit wire for calculating next word of burst write, depending on
|
assign next_addr_word = addr_r[3:2] + 1;
|
// line size of data cache.
|
|
assign next_addr_word = addr_r[`OR1200_DCLS-1:2] + 1;
|
|
|
// Address to cache RAM (tag address also derived from this)
|
// Address to cache RAM (tag address also derived from this)
|
assign dc_addr =
|
assign dc_addr =
|
// First check if we've got a block flush or WB op
|
// First check if we've got a block flush or WB op
|
((dc_block_flush & !cache_spr_block_flush) |
|
((dc_block_flush & !cache_spr_block_flush) |
|
Line 283... |
Line 284... |
// Next, if in writeback loop, when ACKed must immediately
|
// Next, if in writeback loop, when ACKed must immediately
|
// output next word address (the RAM address takes a cycle
|
// output next word address (the RAM address takes a cycle
|
// to increment, but it's needed immediately for burst)
|
// to increment, but it's needed immediately for burst)
|
// otherwise, output our registered address.
|
// otherwise, output our registered address.
|
(state==`OR1200_DCFSM_LOOP2 & biudata_valid & store ) ?
|
(state==`OR1200_DCFSM_LOOP2 & biudata_valid & store ) ?
|
{addr_r[31:4], next_addr_word, 2'b00} : addr_r;
|
{addr_r[31:`OR1200_DCLS], next_addr_word, 2'b00} : addr_r;
|
|
|
`ifdef OR1200_DC_WRITETHROUGH
|
`ifdef OR1200_DC_WRITETHROUGH
|
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
|
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
|
assign writethrough = !dc_no_writethrough;
|
assign writethrough = !dc_no_writethrough;
|
`else
|
`else
|
Line 340... |
Line 341... |
// Get the _early_ ack on first ACK back from wishbone during load only
|
// Get the _early_ ack on first ACK back from wishbone during load only
|
// Condition is that we're in the loop - that it's the first ack we get (can
|
// Condition is that we're in the loop - that it's the first ack we get (can
|
// tell from value of cnt), and we're loading a line to read from it (not
|
// tell from value of cnt), and we're loading a line to read from it (not
|
// loading to write to it, in the case of a write without writethrough.)
|
// loading to write to it, in the case of a write without writethrough.)
|
assign load_miss_ack = ((state== `OR1200_DCFSM_LOOP2) & load &
|
assign load_miss_ack = ((state== `OR1200_DCFSM_LOOP2) & load &
|
(cnt==`OR1200_DCLS-1) & biudata_valid &
|
(cnt==((1 << `OR1200_DCLS) - 4)) & biudata_valid &
|
!(dcqmem_we_i & !writethrough));
|
!(dcqmem_we_i & !writethrough));
|
|
|
assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
|
assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
|
load & cache_inhibit & biudata_valid;
|
load & cache_inhibit & biudata_valid;
|
|
|
Line 360... |
Line 361... |
// Main DC FSM
|
// Main DC FSM
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
state <= `OR1200_DCFSM_IDLE;
|
state <= `OR1200_DCFSM_IDLE;
|
addr_r <= 32'b0;
|
addr_r <= 32'd0;
|
hitmiss_eval <= 1'b0;
|
hitmiss_eval <= 1'b0;
|
store <= 1'b0;
|
store <= 1'b0;
|
load <= 1'b0;
|
load <= 1'b0;
|
cnt <= 3'd0;
|
cnt <= `OR1200_DCLS'd0;
|
cache_miss <= 1'b0;
|
cache_miss <= 1'b0;
|
cache_dirty_needs_writeback <= 1'b0;
|
cache_dirty_needs_writeback <= 1'b0;
|
cache_inhibit <= 1'b0;
|
cache_inhibit <= 1'b0;
|
did_early_load_ack <= 1'b0;
|
did_early_load_ack <= 1'b0;
|
cache_spr_block_flush <= 1'b0;
|
cache_spr_block_flush <= 1'b0;
|
Line 428... |
Line 429... |
load <= 1'b1;
|
load <= 1'b1;
|
store <= 1'b0;
|
store <= 1'b0;
|
end // else: !if(dirty)
|
end // else: !if(dirty)
|
state <= `OR1200_DCFSM_LOOP2;
|
state <= `OR1200_DCFSM_LOOP2;
|
// Set the counter for the burst accesses
|
// Set the counter for the burst accesses
|
cnt <= `OR1200_DCLS-1;
|
cnt <= ((1 << `OR1200_DCLS) - 4);
|
end
|
end
|
else if (// Strobe goes low
|
else if (// Strobe goes low
|
!dcqmem_cycstb_i |
|
!dcqmem_cycstb_i |
|
// Cycle finishes
|
// Cycle finishes
|
(!hitmiss_eval & (biudata_valid | biudata_error)) |
|
(!hitmiss_eval & (biudata_valid | biudata_error)) |
|
Line 451... |
Line 452... |
`OR1200_DCFSM_LOOP2 : begin // loop/abort
|
`OR1200_DCFSM_LOOP2 : begin // loop/abort
|
if (!dc_en| biudata_error) begin
|
if (!dc_en| biudata_error) begin
|
state <= `OR1200_DCFSM_IDLE;
|
state <= `OR1200_DCFSM_IDLE;
|
load <= 1'b0;
|
load <= 1'b0;
|
store <= 1'b0;
|
store <= 1'b0;
|
cnt <= 3'd0;
|
cnt <= `OR1200_DCLS'd0;
|
end
|
end
|
if (biudata_valid & (|cnt)) begin
|
if (biudata_valid & (|cnt)) begin
|
cnt <= cnt - 3'd1;
|
cnt <= cnt - 4;
|
addr_r[3:2] <= addr_r[3:2] + 1'b1;
|
addr_r[`OR1200_DCLS-1:2] <= addr_r[`OR1200_DCLS-1:2] + 1;
|
end
|
end
|
else if (biudata_valid & !(|cnt)) begin
|
else if (biudata_valid & !(|cnt)) begin
|
state <= `OR1200_DCFSM_LOOP3;
|
state <= `OR1200_DCFSM_LOOP3;
|
addr_r <= lsu_addr;
|
addr_r <= lsu_addr;
|
load <= 1'b0;
|
load <= 1'b0;
|
Line 476... |
Line 477... |
`OR1200_DCFSM_LOOP3: begin // figure out next step
|
`OR1200_DCFSM_LOOP3: begin // figure out next step
|
if (cache_dirty_needs_writeback) begin
|
if (cache_dirty_needs_writeback) begin
|
// Just did store of the dirty line so now load new one
|
// Just did store of the dirty line so now load new one
|
load <= 1'b1;
|
load <= 1'b1;
|
// Set the counter for the burst accesses
|
// Set the counter for the burst accesses
|
cnt <= `OR1200_DCLS-1;
|
cnt <= ((1 << `OR1200_DCLS) - 4);
|
// Address of line to be loaded
|
// Address of line to be loaded
|
addr_r <= lsu_addr;
|
addr_r <= lsu_addr;
|
cache_dirty_needs_writeback <= 1'b0;
|
cache_dirty_needs_writeback <= 1'b0;
|
state <= `OR1200_DCFSM_LOOP2;
|
state <= `OR1200_DCFSM_LOOP2;
|
end // if (cache_dirty_needs_writeback)
|
end // if (cache_dirty_needs_writeback)
|
Line 524... |
Line 525... |
`ifdef OR1200_VERBOSE
|
`ifdef OR1200_VERBOSE
|
$display("%t: block flush: dirty block", $time);
|
$display("%t: block flush: dirty block", $time);
|
`endif
|
`endif
|
state <= `OR1200_DCFSM_LOOP2;
|
state <= `OR1200_DCFSM_LOOP2;
|
// Set the counter for the burst accesses
|
// Set the counter for the burst accesses
|
cnt <= `OR1200_DCLS-1;
|
cnt <= ((1 << `OR1200_DCLS) - 4);
|
end
|
end
|
else if (cache_spr_block_flush & !dirty)
|
else if (cache_spr_block_flush & !dirty)
|
begin
|
begin
|
// Line not dirty, just need to invalidate
|
// Line not dirty, just need to invalidate
|
state <= `OR1200_DCFSM_INV6;
|
state <= `OR1200_DCFSM_INV6;
|