-# req.op := req_op;
-# req.valid := req_go;
-# req.mmu_req := r0.mmu_req;
-# req.dcbz := r0.req.dcbz;
-# req.real_addr := ra;
- sync += req.op.eq(req_op)
- sync += req.valid.eq(req_go)
- sync += req.mmu_req.eq(r0.mmu_req)
- sync += req.dcbz.eq(r0.req.dcbz)
- sync += req.real_addr.eq(ra)
-
-# -- Force data to 0 for dcbz
-# if r0.req.dcbz = '0' then
- with m.If(~r0.req.dcbz):
-# req.data := r0.req.data;
- sync += req.data.eq(r0.req.data)
-
-# else
- with m.Else():
-# req.data := (others => '0');
- sync += req.data.eq(0)
-# end if;
-
-# -- Select all bytes for dcbz
-# -- and for cacheable loads
-# if r0.req.dcbz = '1'
-# or (r0.req.load = '1' and r0.req.nc = '0') then
- # Select all bytes for dcbz
- # and for cacheable loads
- with m.If(r0.req.dcbz | (r0.req.load & ~r0.req.nc):
-# req.byte_sel := (others => '1');
- sync += req.byte_sel.eq(1)
-
-# else
- with m.Else():
-# req.byte_sel := r0.req.byte_sel;
- sync += req.byte_sel.eq(r0.req.byte_sel)
-# end if;
-
-# req.hit_way := req_hit_way;
-# req.same_tag := req_same_tag;
- sync += req.hit_way.eq(req_hit_way)
- sync += req.same_tag.eq(req_same_tag)
-
-# -- Store the incoming request from r0,
-# -- if it is a slow request
-# -- Note that r1.full = 1 implies req_op = OP_NONE
-# if req_op = OP_LOAD_MISS or req_op = OP_LOAD_NC
-# or req_op = OP_STORE_MISS
-# or req_op = OP_STORE_HIT then
- # Store the incoming request from r0,
- # if it is a slow request
- # Note that r1.full = 1 implies req_op = OP_NONE
- with m.If(req_op == Op.OP_LOAD_MISS
- | req_op == Op.OP_LOAD_NC
- | req_op == Op.OP_STORE_MISS
- | req_op == Op.OP_STORE_HIT):
-# r1.req <= req;
-# r1.full <= '1';
- sync += r1.req(req)
- sync += r1.full.eq(1)
-# end if;
-# end if;
-#
-# -- Main state machine
-# case r1.state is
- # Main state machine
- with m.Switch(r1.state):
-
-# when IDLE =>
- with m.Case(State.IDLE)
-# r1.wb.adr <= req.real_addr(
-# r1.wb.adr'left downto 0
-# );
-# r1.wb.sel <= req.byte_sel;
-# r1.wb.dat <= req.data;
-# r1.dcbz <= req.dcbz;
-#
-# -- Keep track of our index and way
-# -- for subsequent stores.
-# r1.store_index <= get_index(req.real_addr);
-# r1.store_row <= get_row(req.real_addr);
-# r1.end_row_ix <=
-# get_row_of_line(get_row(req.real_addr)) - 1;
-# r1.reload_tag <= get_tag(req.real_addr);
-# r1.req.same_tag <= '1';
- sync += r1.wb.adr.eq(req.real_addr[0:r1.wb.adr])
- sync += r1.wb.sel.eq(req.byte_sel)
- sync += r1.wb.dat.eq(req.data)
- sync += r1.dcbz.eq(req.dcbz)
-
- # Keep track of our index and way
- # for subsequent stores.
- sync += r1.store_index.eq(get_index(req.real_addr))
- sync += r1.store_row.eq(get_row(req.real_addr))
- sync += r1.end_row_ix.eq(
- get_row_of_line(get_row(req.real_addr))
- )
- sync += r1.reload_tag.eq(get_tag(req.real_addr))
- sync += r1.req.same_tag.eq(1)
-
-# if req.op = OP_STORE_HIT theni
- with m.If(req.op == Op.OP_STORE_HIT):
-# r1.store_way <= req.hit_way;
- sync += r1.store_way.eq(req.hit_way)
-# end if;
-
-# -- Reset per-row valid bits,
-# -- ready for handling OP_LOAD_MISS
-# for i in 0 to ROW_PER_LINE - 1 loop
- # Reset per-row valid bits,
- # ready for handling OP_LOAD_MISS
- for i in range(ROW_PER_LINE):
-# r1.rows_valid(i) <= '0';
- sync += r1.rows_valid[i].eq(0)
-# end loop;
-
-# case req.op is
- with m.Switch(req.op):
-# when OP_LOAD_HIT =>
- with m.Case(Op.OP_LOAD_HIT):
-# -- stay in IDLE state
- # stay in IDLE state
- pass
-
-# when OP_LOAD_MISS =>
- with m.Case(Op.OP_LOAD_MISS):
-# -- Normal load cache miss,
-# -- start the reload machine
-# report "cache miss real addr:" &
-# to_hstring(req.real_addr) & " idx:" &
-# integer'image(get_index(req.real_addr)) &
-# " tag:" & to_hstring(get_tag(req.real_addr));
- # Normal load cache miss,
- # start the reload machine
- print(f"cache miss real addr:" \
- f"{req_real_addr}" \
- f" idx:{get_index(req_real_addr)}" \
- f" tag:{get_tag(req.real_addr)}")
-
-# -- Start the wishbone cycle
-# r1.wb.we <= '0';
-# r1.wb.cyc <= '1';
-# r1.wb.stb <= '1';
- # Start the wishbone cycle
- sync += r1.wb.we.eq(0)
- sync += r1.wb.cyc.eq(1)
- sync += r1.wb.stb.eq(1)
-
-# -- Track that we had one request sent
-# r1.state <= RELOAD_WAIT_ACK;
-# r1.write_tag <= '1';
- # Track that we had one request sent
- sync += r1.state.eq(State.RELOAD_WAIT_ACK)
- sync += r1.write_tag.eq(1)
-
-# when OP_LOAD_NC =>
- with m.Case(Op.OP_LOAD_NC):
-# r1.wb.cyc <= '1';
-# r1.wb.stb <= '1';
-# r1.wb.we <= '0';
-# r1.state <= NC_LOAD_WAIT_ACK;
- sync += r1.wb.cyc.eq(1)
- sync += r1.wb.stb.eq(1)
- sync += r1.wb.we.eq(0)
- sync += r1.state.eq(State.NC_LOAD_WAIT_ACK)
-
-# when OP_STORE_HIT | OP_STORE_MISS =>
- with m.Case(Op.OP_STORE_HIT
- | Op.OP_STORE_MISS):
-# if req.dcbz = '0' then
- with m.If(~req.bcbz):
-# r1.state <= STORE_WAIT_ACK;
-# r1.acks_pending <= to_unsigned(1, 3);
-# r1.full <= '0';
-# r1.slow_valid <= '1';
- sync += r1.state.eq(
- State.STORE_WAIT_ACK
- )
- sync += r1.acks_pending.eq(
- '''TODO to_unsignes(1,3)'''
- )
- sync += r1.full.eq(0)
- sync += r1.slow_valid.eq(1)
-
-# if req.mmu_req = '0' then
- with m.If(~req.mmu_req):
-# r1.ls_valid <= '1';
- sync += r1.ls_valid.eq(1)
-# else
- with m.Else():
-# r1.mmu_done <= '1';
- sync += r1.mmu_done.eq(1)
-# end if;
-
-# if req.op = OP_STORE_HIT then
- with m.If(req.op == Op.OP_STORE_HIT):
-# r1.write_bram <= '1';
- sync += r1.write_bram.eq(1)
-# end if;
-
-# else
- with m.Else():
-# -- dcbz is handled much like a load
-# -- miss except that we are writing
-# -- to memory instead of reading
-# r1.state <= RELOAD_WAIT_ACK;
- # dcbz is handled much like a load
- # miss except that we are writing
- # to memory instead of reading
- sync += r1.state.eq(Op.RELOAD_WAIT_ACK)
-
-# if req.op = OP_STORE_MISS then
- with m.If(req.op == Op.OP_STORE_MISS):
-# r1.write_tag <= '1';
- sync += r1.write_tag.eq(1)
-# end if;
-# end if;
-
-# r1.wb.we <= '1';
-# r1.wb.cyc <= '1';
-# r1.wb.stb <= '1';
- sync += r1.wb.we.eq(1)
- sync += r1.wb.cyc.eq(1)
- sync += r1.wb.stb.eq(1)
-
-# -- OP_NONE and OP_BAD do nothing
-# -- OP_BAD & OP_STCX_FAIL were handled above already
-# when OP_NONE =>
-# when OP_BAD =>
-# when OP_STCX_FAIL =>
- # OP_NONE and OP_BAD do nothing
- # OP_BAD & OP_STCX_FAIL were
- # handled above already
- with m.Case(Op.OP_NONE):
- pass
-
- with m.Case(OP_BAD):
- pass
-
- with m.Case(OP_STCX_FAIL):
- pass
-# end case;
-
-# when RELOAD_WAIT_ACK =>
- with m.Case(State.RELOAD_WAIT_ACK):
-# -- Requests are all sent if stb is 0
- # Requests are all sent if stb is 0
- sync += stbs_done.eq(~r1.wb.stb)
-# stbs_done := r1.wb.stb = '0';
-
-# -- If we are still sending requests,
-# -- was one accepted?
-# if wishbone_in.stall = '0' and not stbs_done then
- # If we are still sending requests,
- # was one accepted?
- with m.If(~wb_in.stall & ~stbs_done):
-# -- That was the last word ? We are done sending.
-# -- Clear stb and set stbs_done so we can handle
-# -- an eventual last ack on the same cycle.
-# if is_last_row_addr(
-# r1.wb.adr, r1.end_row_ix
-# ) then
- # That was the last word?
- # We are done sending.
- # Clear stb and set stbs_done
- # so we can handle an eventual
- # last ack on the same cycle.
- with m.If(is_last_row_addr(
- r1.wb.adr, r1.end_row_ix)):
-# r1.wb.stb <= '0';
-# stbs_done := true;
- sync += r1.wb.stb.eq(0)
- sync += stbs_done.eq(0)
-# end if;
-
-# -- Calculate the next row address
-# r1.wb.adr <= next_row_addr(r1.wb.adr);
- # Calculate the next row address
- sync += r1.wb.adr.eq(next_row_addr(r1.wb.adr))
-# end if;
-
-# -- Incoming acks processing
-# r1.forward_valid1 <= wishbone_in.ack;
- # Incoming acks processing
- sync += r1.forward_valid1.eq(wb_in.ack)
-
-# if wishbone_in.ack = '1' then
- with m.If(wb_in.ack):
-# r1.rows_valid(
-# r1.store_row mod ROW_PER_LINE
-# ) <= '1';
- sync += r1.rows_valid[
- r1.store_row % ROW_PER_LINE
- ].eq(1)
-
-# -- If this is the data we were looking for,
-# -- we can complete the request next cycle.
-# -- Compare the whole address in case the
-# -- request in r1.req is not the one that
-# -- started this refill.
-# if r1.full = '1' and r1.req.same_tag = '1'
-# and ((r1.dcbz = '1' and r1.req.dcbz = '1')
-# or (r1.dcbz = '0' and r1.req.op = OP_LOAD_MISS))
-# and r1.store_row = get_row(r1.req.real_addr) then
- # If this is the data we were looking for,
- # we can complete the request next cycle.
- # Compare the whole address in case the
- # request in r1.req is not the one that
- # started this refill.
- with m.If(r1.full & r1.req.same_tag &
- ((r1.dcbz & r1.req.dcbz)
- (~r1.dcbz &
- r1.req.op == Op.OP_LOAD_MISS)
- ) &
- r1.store_row
- == get_row(r1.req.real_addr):
-# r1.full <= '0';
-# r1.slow_valid <= '1';
- sync += r1.full.eq(0)
- sync += r1.slow_valid.eq(1)
-
-# if r1.mmu_req = '0' then
- with m.If(~r1.mmu_req):
-# r1.ls_valid <= '1';
- sync += r1.ls_valid.eq(1)
-# else
- with m.Else():
-# r1.mmu_done <= '1';
- sync += r1.mmu_done.eq(1)
-# end if;
-# r1.forward_sel <= (others => '1');
-# r1.use_forward1 <= '1';
- sync += r1.forward_sel.eq(1)
- sync += r1.use_forward1.eq(1)
-# end if;
-
-# -- Check for completion
-# if stbs_done and is_last_row(r1.store_row,
-# r1.end_row_ix) then
- # Check for completion
- with m.If(stbs_done &
- is_last_row(r1.store_row,
- r1.end_row_ix)):
-
-# -- Complete wishbone cycle
-# r1.wb.cyc <= '0';
- # Complete wishbone cycle
- sync += r1.wb.cyc.eq(0)
-
-# -- Cache line is now valid
-# cache_valids(r1.store_index)(
-# r1.store_way
-# ) <= '1';
- # Cache line is now valid
- sync += cache_valid_bits[
- r1.store_index
- ][r1.store_way].eq(1)
-
-# r1.state <= IDLE;
- sync += r1.state.eq(State.IDLE)
-# end if;
-
-# -- Increment store row counter
-# r1.store_row <= next_row(r1.store_row);
- # Increment store row counter
- sync += r1.store_row.eq(next_row(
- r1.store_row
- ))
-# end if;
-
-# when STORE_WAIT_ACK =>
- with m.Case(State.STORE_WAIT_ACK):
-# stbs_done := r1.wb.stb = '0';
-# acks := r1.acks_pending;
- sync += stbs_done.eq(~r1.wb.stb)
- sync += acks.eq(r1.acks_pending)
-
-# if r1.inc_acks /= r1.dec_acks then
- with m.If(r1.inc_acks != r1.dec_acks):
-
-# if r1.inc_acks = '1' then
- with m.If(r1.inc_acks):
-# acks := acks + 1;
- sync += acks.eq(acks + 1)
-
-# else
- with m.Else():
-# acks := acks - 1;
- sync += acks.eq(acks - 1)
-# end if;
-# end if;
-
-# r1.acks_pending <= acks;
- sync += r1.acks_pending.eq(acks)
-
-# -- Clear stb when slave accepted request
-# if wishbone_in.stall = '0' then
- # Clear stb when slave accepted request
- with m.If(~wb_in.stall):
-# -- See if there is another store waiting
-# -- to be done which is in the same real page.
-# if req.valid = '1' then
- # See if there is another store waiting
- # to be done which is in the same real page.
- with m.If(req.valid):
-# r1.wb.adr(
-# SET_SIZE_BITS - 1 downto 0
-# ) <= req.real_addr(
-# SET_SIZE_BITS - 1 downto 0
-# );
-# r1.wb.dat <= req.data;
-# r1.wb.sel <= req.byte_sel;
- sync += r1.wb.adr[0:SET_SIZE_BITS].eq(
- req.real_addr[0:SET_SIZE_BITS]
- )
-# end if;
-
-# if acks < 7 and req.same_tag = '1'
-# and (req.op = OP_STORE_MISS
-# or req.op = OP_STORE_HIT) then
- with m.Elif(acks < 7 & req.same_tag &
- (req.op == Op.Op_STORE_MISS
- | req.op == Op.OP_SOTRE_HIT)):
-# r1.wb.stb <= '1';
-# stbs_done := false;
- sync += r1.wb.stb.eq(1)
- sync += stbs_done.eq(0)
-
-# if req.op = OP_STORE_HIT then
- with m.If(req.op == Op.OP_STORE_HIT):
-# r1.write_bram <= '1';
- sync += r1.write_bram.eq(1)
-# end if;
-# r1.full <= '0';
-# r1.slow_valid <= '1';
- sync += r1.full.eq(0)
- sync += r1.slow_valid.eq(1)
-
-# -- Store requests never come from the MMU
-# r1.ls_valid <= '1';
-# stbs_done := false;
-# r1.inc_acks <= '1';
- # Store request never come from the MMU
- sync += r1.ls_valid.eq(1)
- sync += stbs_done.eq(0)
- sync += r1.inc_acks.eq(1)
-# else
- with m.Else():
-# r1.wb.stb <= '0';
-# stbs_done := true;
- sync += r1.wb.stb.eq(0)
- sync += stbs_done.eq(1)
-# end if;
-# end if;
-
-# -- Got ack ? See if complete.
-# if wishbone_in.ack = '1' then
- # Got ack ? See if complete.
- with m.If(wb_in.ack):
-# if stbs_done and acks = 1 then
- with m.If(stbs_done & acks)
-# r1.state <= IDLE;
-# r1.wb.cyc <= '0';
-# r1.wb.stb <= '0';
- sync += r1.state.eq(State.IDLE)
- sync += r1.wb.cyc.eq(0)
- sync += r1.wb.stb.eq(0)
-# end if;
-# r1.dec_acks <= '1';
- sync += r1.dec_acks.eq(1)
-# end if;
-
-# when NC_LOAD_WAIT_ACK =>
- with m.Case(State.NC_LOAD_WAIT_ACK):
-# -- Clear stb when slave accepted request
-# if wishbone_in.stall = '0' then
- # Clear stb when slave accepted request
- with m.If(~wb_in.stall):
-# r1.wb.stb <= '0';
- sync += r1.wb.stb.eq(0)
-# end if;
-
-# -- Got ack ? complete.
-# if wishbone_in.ack = '1' then
- # Got ack ? complete.
- with m.If(wb_in.ack):
-# r1.state <= IDLE;
-# r1.full <= '0';
-# r1.slow_valid <= '1';
- sync += r1.state.eq(State.IDLE)