def __init__(self, pspec):
self.pspec = pspec
self.addr_wid = pspec.addr_wid
- self.data_wid = pspec.reg_wid
- self.adr_lsbs = log2_int(pspec.reg_wid//8)
+ if isinstance(pspec.imem_reg_wid, int):
+ self.data_wid = pspec.imem_reg_wid
+ else:
+ self.data_wid = pspec.reg_wid
+ self.adr_lsbs = log2_int(self.data_wid//8)
self.ibus = Record(make_wb_layout(pspec))
bad_wid = pspec.addr_wid - self.adr_lsbs # TODO: is this correct?
self.f_fetch_err_o = Signal()
self.f_badaddr_o = Signal(bad_wid)
+ # detect whether the wishbone bus is enabled / disabled
+ if (hasattr(pspec, "wb_icache_en") and
+ isinstance(pspec.wb_icache_en, Signal)):
+ self.jtag_en = pspec.wb_icache_en
+ else:
+ self.jtag_en = Const(1, 1) # permanently on
+
+
def __iter__(self):
yield self.a_pc_i
yield self.a_stall_i
def elaborate(self, platform):
m = Module()
- ibus_rdata = Signal.like(self.ibus.dat_r)
- with m.If(self.ibus.cyc):
- with m.If(self.ibus.ack | self.ibus.err | ~self.f_valid_i):
+ with m.If(self.jtag_en): # for safety, JTAG can completely disable WB
+
+ ibus_rdata = Signal.like(self.ibus.dat_r)
+ with m.If(self.ibus.cyc):
+ with m.If(self.ibus.ack | self.ibus.err | ~self.f_valid_i):
+ m.d.sync += [
+ self.ibus.cyc.eq(0),
+ self.ibus.stb.eq(0),
+ self.ibus.sel.eq(0),
+ ibus_rdata.eq(self.ibus.dat_r)
+ ]
+ with m.Elif(self.a_valid_i & ~self.a_stall_i):
m.d.sync += [
- self.ibus.cyc.eq(0),
- self.ibus.stb.eq(0),
- ibus_rdata.eq(self.ibus.dat_r)
+ self.ibus.adr.eq(self.a_pc_i[self.adr_lsbs:]),
+ self.ibus.cyc.eq(1),
+ self.ibus.stb.eq(1),
+ self.ibus.sel.eq((1<<(1<<self.adr_lsbs))-1),
]
- with m.Elif(self.a_valid_i & ~self.a_stall_i):
- m.d.sync += [
- self.ibus.adr.eq(self.a_pc_i[self.adr_lsbs:]),
- self.ibus.cyc.eq(1),
- self.ibus.stb.eq(1)
- ]
- with m.If(self.ibus.cyc & self.ibus.err):
- m.d.sync += [
- self.f_fetch_err_o.eq(1),
- self.f_badaddr_o.eq(self.ibus.adr)
- ]
- with m.Elif(~self.f_stall_i):
- m.d.sync += self.f_fetch_err_o.eq(0)
+ with m.If(self.ibus.cyc & self.ibus.err):
+ m.d.sync += [
+ self.f_fetch_err_o.eq(1),
+ self.f_badaddr_o.eq(self.ibus.adr)
+ ]
+ with m.Elif(~self.f_stall_i):
+ m.d.sync += self.f_fetch_err_o.eq(0)
- m.d.comb += self.a_busy_o.eq(self.ibus.cyc)
+ m.d.comb += self.a_busy_o.eq(self.ibus.cyc)
- with m.If(self.f_fetch_err_o):
- m.d.comb += [
- self.f_busy_o.eq(0),
- self.f_instr_o.eq(0x0)
- ]
- with m.Else():
- m.d.comb += [
- self.f_busy_o.eq(self.ibus.cyc),
- self.f_instr_o.eq(ibus_rdata)
- ]
+ with m.If(self.f_fetch_err_o):
+ m.d.comb += self.f_busy_o.eq(0)
+ with m.Else():
+ m.d.comb += [
+ self.f_busy_o.eq(self.ibus.cyc),
+ self.f_instr_o.eq(ibus_rdata)
+ ]
return m
icache = m.submodules.icache = L1Cache(*self.icache_args)
a_icache_select = Signal()
+
+ # Test whether the target address is inside the L1 cache region.
+ # We use bit masks in order to avoid carry chains from arithmetic
+ # comparisons. This restricts the region boundaries to powers of 2.
+
+ # TODO: minerva defaults adr_lsbs to 2. check this code
+ with m.Switch(self.a_pc_i[self.adr_lsbs:]):
+ def addr_below(limit):
+ assert limit in range(1, 2**30 + 1)
+ range_bits = log2_int(limit)
+ const_bits = 30 - range_bits
+ return "{}{}".format("0" * const_bits, "-" * range_bits)
+
+ if icache.base >= 4: # XX (1<<self.adr_lsbs?)
+ with m.Case(addr_below(icache.base >> self.adr_lsbs)):
+ m.d.comb += a_icache_select.eq(0)
+ with m.Case(addr_below(icache.limit >> self.adr_lsbs)):
+ m.d.comb += a_icache_select.eq(1)
+ with m.Default():
+ m.d.comb += a_icache_select.eq(0)
+
f_icache_select = Signal()
+ f_flush = Signal()
- m.d.comb += a_icache_select.eq((self.a_pc_i >= icache.base) &
- (self.a_pc_i < icache.limit))
with m.If(~self.a_stall_i):
- m.d.sync += f_icache_select.eq(a_icache_select)
+ m.d.sync += [
+ f_icache_select.eq(a_icache_select),
+ f_flush.eq(self.a_flush),
+ ]
m.d.comb += [
icache.s1_addr.eq(self.a_pc_i[self.adr_lsbs:]),
m.d.sync += [
bare_port.cyc.eq(0),
bare_port.stb.eq(0),
+ bare_port.sel.eq(0),
bare_rdata.eq(bare_port.dat_r)
]
with m.Elif(~a_icache_select & self.a_valid_i & ~self.a_stall_i):
m.d.sync += [
bare_port.cyc.eq(1),
bare_port.stb.eq(1),
+ bare_port.sel.eq((1<<(1<<self.adr_lsbs))-1),
bare_port.adr.eq(self.a_pc_i[self.adr_lsbs:])
]
+ m.d.comb += self.a_busy_o.eq(bare_port.cyc)
+
with m.If(self.ibus.cyc & self.ibus.err):
m.d.sync += [
self.f_fetch_err_o.eq(1),
with m.Elif(~self.f_stall_i):
m.d.sync += self.f_fetch_err_o.eq(0)
- with m.If(a_icache_select):
- m.d.comb += self.a_busy_o.eq(0)
- with m.Else():
- m.d.comb += self.a_busy_o.eq(bare_port.cyc)
-
- with m.If(self.f_fetch_err_o):
- m.d.comb += [
- self.f_busy_o.eq(0),
- self.f_instr_o.eq(0x0)
- ]
+ with m.If(f_flush):
+ m.d.comb += self.f_busy_o.eq(~icache.s2_flush_ack)
+ with m.Elif(self.f_fetch_err_o):
+ m.d.comb += self.f_busy_o.eq(0)
with m.Elif(f_icache_select):
m.d.comb += [
self.f_busy_o.eq(icache.s2_miss),