Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: bccc5f5
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c129c98
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Mar 31, 2012

  1. asmicon/bankmachine: fixes

    Sebastien Bourdeauducq committed Mar 31, 2012
    Copy the full SHA
    ac7d89a View commit details
  2. tb/asmicon/bankmachine: selector test bench

    Sebastien Bourdeauducq committed Mar 31, 2012
    Copy the full SHA
    c129c98 View commit details
Showing with 132 additions and 16 deletions.
  1. +30 −16 milkymist/asmicon/bankmachine.py
  2. +25 −0 tb/asmicon/common.py
  3. +77 −0 tb/asmicon/selector.py
46 changes: 30 additions & 16 deletions milkymist/asmicon/bankmachine.py
Original file line number Diff line number Diff line change
@@ -13,16 +13,25 @@ def __init__(self, geom_settings, address_align):
self.address_align = address_align

self._b1 = self.geom_settings.col_a - self.address_align
self._b2 = self._b1 + self.geom_settings.row_a

def bank(self, address):
return address[self._b2:]
self._b2 = self._b1 + self.geom_settings.bank_a

def row(self, address):
return address[self._b1:self._b2]
if isinstance(address, int):
return address >> self._b2
else:
return address[self._b2:]

def bank(self, address):
if isinstance(address, int):
return (address & (2**self._b2 - 1)) >> self._b1
else:
return address[self._b1:self._b2]

def col(self, address):
return Cat(Constant(0, BV(self.address_align)), address[:self._b1])
if isinstance(address, int):
return (address & (2**self._b1 - 1)) << self.address_align
else:
return Cat(Constant(0, BV(self.address_align)), address[:self._b1])

class _Selector:
def __init__(self, slicer, bankn, slots):
@@ -46,8 +55,8 @@ def get_fragment(self):
for slot in self.slots:
outstanding = Signal()
comb.append(outstanding.eq(
self.slicer.bank(slot.adr) == self.bankn & \
slot.state == SLOT_PENDING
(self.slicer.bank(slot.adr) == self.bankn) & \
(slot.state == SLOT_PENDING)
))
outstandings.append(outstanding)

@@ -69,18 +78,18 @@ def get_fragment(self):
)
]
hits = []
for slot in self.slots:
for slot, os in zip(self.slots, outstandings):
hit = Signal()
comb.append(hit.eq(self.slicer.row(slot.adr) == openrow))
comb.append(hit.eq((self.slicer.row(slot.adr) == openrow) & os))
hits.append(hit)

# Determine best request
rr = RoundRobin(self.nslots, SP_CE)
has_hit = Signal()
comb.append(has_hit.eq(optree("|", hits)))

best_hit = [rr.request[i].eq(hit & os)
for i, (hit, os) in enumerate(zip(hits, outstandings))]
best_hit = [rr.request[i].eq(hit)
for i, hit in enumerate(hits)]
best_fallback = [rr.request[i].eq(os)
for i, os in enumerate(outstandings)]
select_stmt = If(has_hit,
@@ -91,10 +100,15 @@ def get_fragment(self):

if self.slots[0].time:
# Implement anti-starvation timer
matures = []
for slot, os in zip(self.slots, outstandings):
mature = Signal()
comb.append(mature.eq(slot.mature & os))
matures.append(mature)
has_mature = Signal()
comb.append(has_mature.eq(optree("|", [slot.mature for slot in self.slots])))
best_mature = [rr.request[i].eq(slot.mature & os)
for i, (slot, os) in enumerate(zip(self.slots, outstandings))]
comb.append(has_mature.eq(optree("|", matures)))
best_mature = [rr.request[i].eq(mature)
for i, mature in enumerate(matures)]
select_stmt = If(has_mature, *best_mature).Else(select_stmt)
comb.append(select_stmt)

@@ -109,7 +123,7 @@ def get_fragment(self):
rr.ce.eq(self.ack),
self.tag.eq(rr.grant)
]
comb += [slot.process.eq(rr.grant == i & self.ack)
comb += [slot.process.eq((rr.grant == i) & self.stb & self.ack)
for i, slot in enumerate(self.slots)]

return Fragment(comb, sync) + rr.get_fragment()
25 changes: 25 additions & 0 deletions tb/asmicon/common.py
Original file line number Diff line number Diff line change
@@ -39,3 +39,28 @@ def do_simulation(self, s):

def get_fragment(self):
return Fragment(sim=[self.do_simulation])

class SlotsLogger:
def __init__(self, slicer, slots):
self.slicer = slicer
self.slots = slots

def do_simulation(self, sim):
state_strs = ["EMPTY", "PEND", "PRCESS"]
rw_strs = ["RD", "WR"]
print("\t" + "\t".join([str(x) for x in range(len(self.slots))]))
print("State:\t" + "\t".join([state_strs[sim.rd(s.state)] for s in self.slots]))
print("RW:\t" + "\t".join([rw_strs[sim.rd(s.we)] for s in self.slots]))
print("Row:\t" + "\t".join([str(self.slicer.row(sim.rd(s.adr))) for s in self.slots]))
print("Bank:\t" + "\t".join([str(self.slicer.bank(sim.rd(s.adr))) for s in self.slots]))
print("Col:\t" + "\t".join([str(self.slicer.col(sim.rd(s.adr))) for s in self.slots]))
times = []
for s in self.slots:
if s.time:
times.append(str(sim.rd(s._counter)) + "/" + str(s.time))
else:
times.append("N/A")
print("Time:\t" + "\t".join(times))

def get_fragment(self):
return Fragment(sim=[self.do_simulation])
77 changes: 77 additions & 0 deletions tb/asmicon/selector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from migen.fhdl.structure import *
from migen.bus.asmibus import *
from migen.sim.generic import Simulator, TopLevel
from migen.sim.icarus import Runner

from milkymist import asmicon
from milkymist.asmicon.bankmachine import _AddressSlicer, _Selector, _Buffer

from common import SlotsLogger

sdram_geom = asmicon.GeomSettings(
bank_a=2,
row_a=13,
col_a=10
)

def my_generator(dt, offset):
for t in range(dt):
yield None
for x in range(10):
t = TRead(x + offset)
yield t

class Selector:
def __init__(self, slicer, bankn, slots):
self.selector = _Selector(slicer, bankn, slots)
self.queue = []

def do_simulation(self, s):
if s.rd(self.selector.stb):
tag = s.rd(self.selector.tag)
self.queue.append(tag)
print("==> SELECTED: " + str(tag))
print("")

def get_fragment(self):
comb = [self.selector.ack.eq(1)]
return self.selector.get_fragment() + Fragment(comb, sim=[self.do_simulation])

class Completer:
def __init__(self, hub, queue):
self.hub = hub
self.queue = queue

def do_simulation(self, s):
if self.queue:
tag = self.queue.pop()
s.wr(self.hub.call, 1)
s.wr(self.hub.tag_call, tag)
else:
s.wr(self.hub.call, 0)

def get_fragment(self):
return Fragment(sim=[self.do_simulation])

def main():
hub = Hub(12, 128, 8)
initiators = [Initiator(hub.get_port(), my_generator(0, 2200*(i//6)+i*10))
for i in range(8)]
hub.finalize()

slots = hub.get_slots()
slicer = _AddressSlicer(sdram_geom, 2)
logger = SlotsLogger(slicer, slots)
selector = Selector(slicer, 0, slots)
completer = Completer(hub, selector.queue)

def end_simulation(s):
s.interrupt = all([i.done for i in initiators])

fragment = hub.get_fragment() + sum([i.get_fragment() for i in initiators], Fragment()) + \
logger.get_fragment() + selector.get_fragment() + completer.get_fragment() + \
Fragment(sim=[end_simulation])
sim = Simulator(fragment, Runner(), TopLevel("my.vcd"))
sim.run()

main()