wishbone2lasmi: support lasmim data_width < wishbone data_width

This commit is contained in:
Florent Kermarrec 2014-04-18 13:49:58 +02:00 committed by Sebastien Bourdeauducq
parent 8c03cb0491
commit 86f852a5f1
1 changed files with 52 additions and 19 deletions

View File

@ -6,29 +6,29 @@ from migen.genlib.record import Record, layout_len
# cachesize (in 32-bit words) is the size of the data store, must be a power of 2 # cachesize (in 32-bit words) is the size of the data store, must be a power of 2
class WB2LASMI(Module): class WB2LASMI(Module):
def __init__(self, cachesize, lasmim, wbm=None): def __init__(self, cachesize, lasmim):
if wbm is None: self.wishbone = wishbone.Interface()
wbm = wishbone.Interface()
self.wishbone = wbm
### ###
data_width = flen(self.wishbone.dat_r) data_width = flen(self.wishbone.dat_r)
if lasmim.dw < data_width: if lasmim.dw > data_width and (lasmim.dw % data_width) != 0:
raise ValueError("LASMI data width must be >= {dw}".format(dw=data_width))
if (lasmim.dw % data_width) != 0:
raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width)) raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width))
if lasmim.dw < data_width and (data_width % lasmim.dw) != 0:
raise ValueError("WISHBONE data width must be a multiple of {dw}".format(dw=lasmim.dw))
# Split address: # Split address:
# TAG | LINE NUMBER | LINE OFFSET # TAG | LINE NUMBER | LINE OFFSET
offsetbits = log2_int(lasmim.dw//data_width) offsetbits = log2_int(max(lasmim.dw//data_width, 1))
addressbits = lasmim.aw + offsetbits addressbits = lasmim.aw + offsetbits
linebits = log2_int(cachesize) - offsetbits linebits = log2_int(cachesize) - offsetbits
tagbits = addressbits - linebits tagbits = addressbits - linebits
wordbits = data_width//lasmim.dw
adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits) adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
word = Signal(wordbits) if wordbits else None
# Data memory # Data memory
data_mem = Memory(lasmim.dw, 2**linebits) data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits)
data_port = data_mem.get_port(write_capable=True, we_granularity=8) data_port = data_mem.get_port(write_capable=True, we_granularity=8)
self.specials += data_mem, data_port self.specials += data_mem, data_port
@ -43,16 +43,16 @@ class WB2LASMI(Module):
self.comb += [ self.comb += [
data_port.adr.eq(adr_line), data_port.adr.eq(adr_line),
If(write_from_lasmi, If(write_from_lasmi,
data_port.dat_w.eq(lasmim.dat_r), displacer(lasmim.dat_r, word, data_port.dat_w),
data_port.we.eq(Replicate(1, lasmim.dw//8)) displacer(Replicate(1, lasmim.dw//8), word, data_port.we)
).Else( ).Else(
data_port.dat_w.eq(Replicate(self.wishbone.dat_w, lasmim.dw//data_width)), data_port.dat_w.eq(Replicate(self.wishbone.dat_w, max(lasmim.dw//data_width, 1))),
If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack, If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
) )
), ),
If(write_to_lasmi, If(write_to_lasmi,
lasmim.dat_w.eq(data_port.dat_r), chooser(data_port.dat_r, word, lasmim.dat_w),
lasmim.dat_we.eq(2**(lasmim.dw//8)-1) lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
), ),
chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
@ -73,13 +73,34 @@ class WB2LASMI(Module):
self.comb += [ self.comb += [
tag_port.adr.eq(adr_line), tag_port.adr.eq(adr_line),
tag_di.tag.eq(adr_tag), tag_di.tag.eq(adr_tag)
lasmim.adr.eq(Cat(adr_line, tag_do.tag))
] ]
if word is not None:
self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
else:
self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))
# Lasmim word computation, word_clr and word_inc will be simplified
# at synthesis when wordbits=0
word_clr = Signal()
word_inc = Signal()
if word is not None:
self.sync += \
If(word_clr,
word.eq(0),
).Elif(word_inc,
word.eq(word+1)
)
def word_is_last(word):
if word is not None:
return word == 2**wordbits-1
else:
return 1
# Control FSM # Control FSM
assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1) assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
fsm = FSM() fsm = FSM(reset_state="IDLE")
self.submodules += fsm self.submodules += fsm
fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1) fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1)
@ -89,6 +110,7 @@ class WB2LASMI(Module):
If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT")) If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
) )
fsm.act("TEST_HIT", fsm.act("TEST_HIT",
word_clr.eq(1),
If(tag_do.tag == adr_tag, If(tag_do.tag == adr_tag,
self.wishbone.ack.eq(1), self.wishbone.ack.eq(1),
If(self.wishbone.we, If(self.wishbone.we,
@ -115,12 +137,18 @@ class WB2LASMI(Module):
) )
fsm.act("EVICT_DATA", fsm.act("EVICT_DATA",
write_to_lasmi.eq(1), write_to_lasmi.eq(1),
NextState("REFILL_WRTAG") word_inc.eq(1),
If(word_is_last(word),
NextState("REFILL_WRTAG"),
).Else(
NextState("EVICT_REQUEST")
)
) )
fsm.act("REFILL_WRTAG", fsm.act("REFILL_WRTAG",
# Write the tag first to set the LASMI address # Write the tag first to set the LASMI address
tag_port.we.eq(1), tag_port.we.eq(1),
word_clr.eq(1),
NextState("REFILL_REQUEST") NextState("REFILL_REQUEST")
) )
fsm.act("REFILL_REQUEST", fsm.act("REFILL_REQUEST",
@ -132,5 +160,10 @@ class WB2LASMI(Module):
) )
fsm.act("REFILL_DATA", fsm.act("REFILL_DATA",
write_from_lasmi.eq(1), write_from_lasmi.eq(1),
NextState("TEST_HIT") word_inc.eq(1),
If(word_is_last(word),
NextState("TEST_HIT"),
).Else(
NextState("REFILL_REQUEST")
)
) )