from enum import Enum, unique
from nmigen import Module, Signal, Elaboratable, Cat, Repl, Array, Const
from enum import Enum, unique
from nmigen import Module, Signal, Elaboratable, Cat, Repl, Array, Const
from random import randint
from nmigen.cli import main
from nmutil.iocontrol import RecordObject
from random import randint
from nmigen.cli import main
from nmutil.iocontrol import RecordObject
from nmigen.utils import log2_int
from soc.experiment.mem_types import (LoadStore1ToDCacheType,
DCacheToLoadStore1Type,
from nmigen.utils import log2_int
from soc.experiment.mem_types import (LoadStore1ToDCacheType,
DCacheToLoadStore1Type,
WBIOMasterOut, WBIOSlaveOut)
from soc.experiment.cache_ram import CacheRam
WBIOMasterOut, WBIOSlaveOut)
from soc.experiment.cache_ram import CacheRam
# for test
from nmigen_soc.wishbone.sram import SRAM
from nmigen import Memory
from nmigen.cli import rtlil
# for test
from nmigen_soc.wishbone.sram import SRAM
from nmigen import Memory
from nmigen.cli import rtlil
-if True:
- from nmigen.back.pysim import Simulator, Delay, Settle
-else:
- from nmigen.sim.cxxsim import Simulator, Delay, Settle
+
+# NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
+# Also, check out the cxxsim nmigen branch, and latest yosys from git
+from nmutil.sim_tmp_alternative import Simulator
+
+from nmutil.util import wrap
NUM_LINES = 16 # Number of lines in a set
NUM_WAYS = 4 # Number of ways
TLB_SET_SIZE = 64 # L1 DTLB entries per set
NUM_LINES = 16 # Number of lines in a set
NUM_WAYS = 4 # Number of ways
TLB_SET_SIZE = 64 # L1 DTLB entries per set
(TAG_BITS, INDEX_BITS, ROW_BITS,
ROW_OFF_BITS, LINE_OFF_BITS, ROW_LINE_BITS))
print ("index @: %d-%d" % (LINE_OFF_BITS, SET_SIZE_BITS))
(TAG_BITS, INDEX_BITS, ROW_BITS,
ROW_OFF_BITS, LINE_OFF_BITS, ROW_LINE_BITS))
print ("index @: %d-%d" % (LINE_OFF_BITS, SET_SIZE_BITS))
def CacheTagArray():
return Array(Signal(TAG_RAM_WIDTH, name="cachetag_%d" % x) \
for x in range(NUM_LINES))
def CacheTagArray():
return Array(Signal(TAG_RAM_WIDTH, name="cachetag_%d" % x) \
for x in range(NUM_LINES))
self.write_bram = Signal()
self.write_tag = Signal()
self.slow_valid = Signal()
self.write_bram = Signal()
self.write_tag = Signal()
self.slow_valid = Signal()
self.wb = WBMasterOut("wb")
self.reload_tag = Signal(TAG_BITS)
self.store_way = Signal(WAY_BITS)
self.wb = WBMasterOut("wb")
self.reload_tag = Signal(TAG_BITS)
self.store_way = Signal(WAY_BITS)
sync += r.req.priv_mode.eq(1)
sync += r.req.addr.eq(m_in.addr)
sync += r.req.data.eq(m_in.pte)
sync += r.req.priv_mode.eq(1)
sync += r.req.addr.eq(m_in.addr)
sync += r.req.data.eq(m_in.pte)
setattr(m.submodules, "maybe_plru_%d" % i, tlb_plru)
tlb_plru_acc_en = Signal()
comb += tlb_plru_acc_en.eq(r1.tlb_hit & (r1.tlb_hit_index == i))
comb += tlb_plru.acc_en.eq(tlb_plru_acc_en)
setattr(m.submodules, "maybe_plru_%d" % i, tlb_plru)
tlb_plru_acc_en = Signal()
comb += tlb_plru_acc_en.eq(r1.tlb_hit & (r1.tlb_hit_index == i))
comb += tlb_plru.acc_en.eq(tlb_plru_acc_en)
comb += tlb_plru_victim[i].eq(tlb_plru.lru_o)
def tlb_search(self, m, tlb_req_index, r0, r0_valid,
comb += tlb_plru_victim[i].eq(tlb_plru.lru_o)
def tlb_search(self, m, tlb_req_index, r0, r0_valid,
comb += ra.eq(Cat(Const(0, ROW_OFF_BITS),
r0.req.addr[ROW_OFF_BITS:TLB_LG_PGSZ],
pte[TLB_LG_PGSZ:REAL_ADDR_BITS]))
comb += ra.eq(Cat(Const(0, ROW_OFF_BITS),
r0.req.addr[ROW_OFF_BITS:TLB_LG_PGSZ],
pte[TLB_LG_PGSZ:REAL_ADDR_BITS]))
- comb += perm_attr.eq(extract_perm_attr(pte))
+ comb += perm_attr.reference.eq(pte[8])
+ comb += perm_attr.changed.eq(pte[7])
+ comb += perm_attr.nocache.eq(pte[5])
+ comb += perm_attr.priv.eq(pte[3])
+ comb += perm_attr.rd_perm.eq(pte[2])
+ comb += perm_attr.wr_perm.eq(pte[1])
with m.Else():
comb += ra.eq(Cat(Const(0, ROW_OFF_BITS),
r0.req.addr[ROW_OFF_BITS:REAL_ADDR_BITS]))
with m.Else():
comb += ra.eq(Cat(Const(0, ROW_OFF_BITS),
r0.req.addr[ROW_OFF_BITS:REAL_ADDR_BITS]))
comb += plru_victim[i].eq(plru.lru_o)
def cache_tag_read(self, m, r0_stall, req_index, cache_tag_set, cache_tags):
comb += plru_victim[i].eq(plru.lru_o)
def cache_tag_read(self, m, r0_stall, req_index, cache_tag_set, cache_tags):
# For a store, consider this a hit even if the row isn't
# valid since it will be by the time we perform the store.
# For a load, check the appropriate row valid bit.
# For a store, consider this a hit even if the row isn't
# valid since it will be by the time we perform the store.
# For a load, check the appropriate row valid bit.
- def writeback_control(self, m, r1, cache_out):
+ def writeback_control(self, m, r1, cache_out_row):
- def rams(self, m, r1, early_req_row, cache_out, replace_way):
+ def rams(self, m, r1, early_req_row, cache_out_row, replace_way):
"""rams
Generate a cache RAM for each way. This handles the normal
reads, writes from reloads and the special store-hit update
"""rams
Generate a cache RAM for each way. This handles the normal
reads, writes from reloads and the special store-hit update
wr_sel_m = Signal(ROW_SIZE)
_d_out = Signal(WB_DATA_BITS, name="dout_%d" % i)
wr_sel_m = Signal(ROW_SIZE)
_d_out = Signal(WB_DATA_BITS, name="dout_%d" % i)
setattr(m.submodules, "cacheram_%d" % i, way)
comb += way.rd_en.eq(do_read)
setattr(m.submodules, "cacheram_%d" % i, way)
comb += way.rd_en.eq(do_read)
sync += r1.wb.sel.eq(req.byte_sel)
sync += r1.wb.dat.eq(req.data)
sync += r1.dcbz.eq(req.dcbz)
sync += r1.wb.sel.eq(req.byte_sel)
sync += r1.wb.dat.eq(req.data)
sync += r1.dcbz.eq(req.dcbz)
# Clear stb and set ld_stbs_done
# so we can handle an eventual
# last ack on the same cycle.
# Clear stb and set ld_stbs_done
# so we can handle an eventual
# last ack on the same cycle.
- rarange = Signal(LINE_OFF_BITS-ROW_OFF_BITS)
- comb += rarange.eq(r1.wb.adr[ROW_OFF_BITS:LINE_OFF_BITS]+1)
- sync += r1.wb.adr[ROW_OFF_BITS:LINE_OFF_BITS].eq(rarange)
+ row = Signal(LINE_OFF_BITS-ROW_OFF_BITS)
+ comb += row.eq(r1.real_adr[ROW_OFF_BITS:])
+ sync += r1.real_adr[ROW_OFF_BITS:LINE_OFF_BITS].eq(row+1)
# If this is the data we were looking for,
# we can complete the request next cycle.
# If this is the data we were looking for,
# we can complete the request next cycle.
sync += log_out.eq(Cat(r1.state[:3], valid_ra, tlb_hit_way[:3],
stall_out, req_op[:3], d_out.valid, d_out.error,
r1.wb.cyc, r1.wb.stb, wb_in.ack, wb_in.stall,
sync += log_out.eq(Cat(r1.state[:3], valid_ra, tlb_hit_way[:3],
stall_out, req_op[:3], d_out.valid, d_out.error,
r1.wb.cyc, r1.wb.stb, wb_in.ack, wb_in.stall,
comb += self.wb_out.eq(r1.wb)
# call sub-functions putting everything together, using shared
comb += self.wb_out.eq(r1.wb)
# call sub-functions putting everything together, using shared
r0_valid, r0, reservation)
self.reservation_reg(m, r0_valid, access_ok, set_rsrv, clear_rsrv,
reservation, r0)
r0_valid, r0, reservation)
self.reservation_reg(m, r0_valid, access_ok, set_rsrv, clear_rsrv,
reservation, r0)
- self.writeback_control(m, r1, cache_out)
- self.rams(m, r1, early_req_row, cache_out, replace_way)
+ self.writeback_control(m, r1, cache_out_row)
+ self.rams(m, r1, early_req_row, cache_out_row, replace_way)
self.dcache_fast_hit(m, req_op, r0_valid, r0, r1,
req_hit_way, req_index, req_tag, access_ok,
tlb_hit, tlb_hit_way, tlb_req_index)
self.dcache_fast_hit(m, req_op, r0_valid, r0, r1,
req_hit_way, req_index, req_tag, access_ok,
tlb_hit, tlb_hit_way, tlb_req_index)
m.d.comb += sram.bus.stb.eq(dut.wb_out.stb)
m.d.comb += sram.bus.we.eq(dut.wb_out.we)
m.d.comb += sram.bus.sel.eq(dut.wb_out.sel)
m.d.comb += sram.bus.stb.eq(dut.wb_out.stb)
m.d.comb += sram.bus.we.eq(dut.wb_out.we)
m.d.comb += sram.bus.sel.eq(dut.wb_out.sel)