From a0f1ee3fbbd69140e66184b77c63dbda5d6f331b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 15 Jul 2013 17:45:55 +0200 Subject: [PATCH] lasmicon: update test benches --- tb/asmicon/asmicon.py | 38 -------------- tb/asmicon/asmicon_wb.py | 46 ---------------- tb/asmicon/bankmachine.py | 47 ----------------- tb/asmicon/selector.py | 76 --------------------------- tb/lasmicon/bankmachine.py | 44 ++++++++++++++++ tb/{asmicon => lasmicon}/common.py | 63 ++++++---------------- tb/lasmicon/lasmicon.py | 45 ++++++++++++++++ tb/lasmicon/lasmicon_wb.py | 43 +++++++++++++++ tb/{asmicon => lasmicon}/refresher.py | 20 ++++--- 9 files changed, 157 insertions(+), 265 deletions(-) delete mode 100644 tb/asmicon/asmicon.py delete mode 100644 tb/asmicon/asmicon_wb.py delete mode 100644 tb/asmicon/bankmachine.py delete mode 100644 tb/asmicon/selector.py create mode 100644 tb/lasmicon/bankmachine.py rename tb/{asmicon => lasmicon}/common.py (55%) create mode 100644 tb/lasmicon/lasmicon.py create mode 100644 tb/lasmicon/lasmicon_wb.py rename tb/{asmicon => lasmicon}/refresher.py (68%) diff --git a/tb/asmicon/asmicon.py b/tb/asmicon/asmicon.py deleted file mode 100644 index 399a18b3..00000000 --- a/tb/asmicon/asmicon.py +++ /dev/null @@ -1,38 +0,0 @@ -from migen.fhdl.std import * -from migen.bus.asmibus import * -from migen.sim.generic import Simulator, TopLevel - -from milkymist.asmicon import * - -from common import sdram_phy, sdram_geom, sdram_timing, DFILogger - -def my_generator_r(): - for x in range(50): - t = TRead(x) - yield t - print("reads done") - -def my_generator_w(): - for x in range(50): - t = TWrite(x, x) - yield t - print("writes done") - -def main(): - dut = ASMIcon(sdram_phy, sdram_geom, sdram_timing) - initiator1 = Initiator(my_generator_r(), dut.hub.get_port()) - initiator2 = Initiator(my_generator_w(), dut.hub.get_port()) - dut.finalize() - - logger = DFILogger(dut.dfi) - - def end_simulation(s): - s.interrupt = initiator1.done and initiator2.done - - fragment = dut.get_fragment() + initiator1.get_fragment() + initiator2.get_fragment() + \ - logger.get_fragment() + \ - Fragment(sim=[end_simulation]) - sim = Simulator(fragment, TopLevel("my.vcd")) - sim.run(700) - -main() diff --git a/tb/asmicon/asmicon_wb.py b/tb/asmicon/asmicon_wb.py deleted file mode 100644 index e5efe0f4..00000000 --- a/tb/asmicon/asmicon_wb.py +++ /dev/null @@ -1,46 +0,0 @@ -from migen.fhdl.std import * -from migen.bus import wishbone, wishbone2asmi, asmibus -from migen.sim.generic import Simulator, TopLevel - -from milkymist.asmicon import * - -from common import sdram_phy, sdram_geom, sdram_timing, DFILogger - -l2_size = 8192 # in bytes - -def my_generator(): - for x in range(20): - t = TWrite(x, x) - yield t - print(str(t) + " delay=" + str(t.latency)) - for x in range(20): - t = TRead(x) - yield t - print(str(t) + " delay=" + str(t.latency)) - for x in range(20): - t = TRead(x+l2_size//4) - yield t - print(str(t) + " delay=" + str(t.latency)) - -def main(): - controller = ASMIcon(sdram_phy, sdram_geom, sdram_timing) - bridge = wishbone2asmi.WB2ASMI(l2_size//4, controller.hub.get_port()) - controller.finalize() - initiator = wishbone.Initiator(my_generator()) - conn = wishbone.InterconnectPointToPoint(initiator.bus, bridge.wishbone) - - logger = DFILogger(controller.dfi) - - def end_simulation(s): - s.interrupt = initiator.done - - fragment = controller.get_fragment() + \ - bridge.get_fragment() + \ - initiator.get_fragment() + \ - conn.get_fragment() + \ - logger.get_fragment() + \ - Fragment(sim=[end_simulation]) - sim = Simulator(fragment, TopLevel("my.vcd")) - sim.run() - -main() diff --git a/tb/asmicon/bankmachine.py b/tb/asmicon/bankmachine.py deleted file mode 100644 index fd495d6e..00000000 --- a/tb/asmicon/bankmachine.py +++ /dev/null @@ -1,47 +0,0 @@ -from migen.fhdl.std import * -from migen.bus.asmibus import * -from migen.sim.generic import Simulator, TopLevel - -from milkymist.asmicon.bankmachine import * - -from common import sdram_geom, sdram_timing, CommandLogger - -def my_generator(): - for x in range(10): - t = TWrite(x) - yield t - for x in range(10): - t = TWrite(x + 2200) - yield t - -class Completer: - def __init__(self, hub, cmd): - self.hub = hub - self.cmd = cmd - - def get_fragment(self): - sync = [ - self.hub.call.eq(self.cmd.stb & self.cmd.ack & (self.cmd.is_read | self.cmd.is_write)), - self.hub.tag_call.eq(self.cmd.tag) - ] - return Fragment(sync=sync) - -def main(): - hub = Hub(12, 128, 2) - initiator = Initiator(hub.get_port(), my_generator()) - hub.finalize() - - dut = BankMachine(sdram_geom, sdram_timing, 2, 0, hub.get_slots()) - logger = CommandLogger(dut.cmd, True) - completer = Completer(hub, dut.cmd) - - def end_simulation(s): - s.interrupt = initiator.done - - fragment = hub.get_fragment() + initiator.get_fragment() + \ - dut.get_fragment() + logger.get_fragment() + completer.get_fragment() + \ - Fragment(sim=[end_simulation]) - sim = Simulator(fragment, TopLevel("my.vcd")) - sim.run() - -main() diff --git a/tb/asmicon/selector.py b/tb/asmicon/selector.py deleted file mode 100644 index ee987814..00000000 --- a/tb/asmicon/selector.py +++ /dev/null @@ -1,76 +0,0 @@ -from random import Random - -from migen.fhdl.std import * -from migen.bus.asmibus import * -from migen.sim.generic import Simulator, TopLevel - -from milkymist.asmicon.bankmachine import _AddressSlicer, _SimpleSelector - -from common import SlotsLogger, sdram_geom - -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 = _SimpleSelector(slicer, bankn, slots) - self.queue = [] - self.prng = Random(876) - - def do_simulation(self, s): - if self.prng.randrange(0, 5): - s.wr(self.selector.ack, 1) - else: - s.wr(self.selector.ack, 0) - if s.rd(self.selector.stb) and s.rd(self.selector.ack): - tag = s.rd(self.selector.tag) - self.queue.append(tag) - print("==> SELECTED: " + str(tag)) - print("") - - def get_fragment(self): - return self.selector.get_fragment() + \ - Fragment(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, TopLevel("my.vcd")) - sim.run() - -main() diff --git a/tb/lasmicon/bankmachine.py b/tb/lasmicon/bankmachine.py new file mode 100644 index 00000000..3564183a --- /dev/null +++ b/tb/lasmicon/bankmachine.py @@ -0,0 +1,44 @@ +from migen.fhdl.std import * +from migen.bus.lasmibus import * +from migen.sim.generic import Simulator, TopLevel + +from milkymist.lasmicon.bankmachine import * + +from common import sdram_geom, sdram_timing, CommandLogger + +def my_generator(): + for x in range(10): + yield True, x + for x in range(10): + yield False, 128*x + +class TB(Module): + def __init__(self): + self.req = Interface(32, 32, 1, + sdram_timing.req_queue_size, sdram_timing.read_latency, sdram_timing.write_latency) + self.submodules.dut = BankMachine(sdram_geom, sdram_timing, 2, 0, self.req) + self.submodules.logger = CommandLogger(self.dut.cmd, True) + self.generator = my_generator() + self.dat_ack_cnt = 0 + + def do_simulation(self, s): + if s.rd(self.req.dat_ack): + self.dat_ack_cnt += 1 + if s.rd(self.req.req_ack): + try: + we, adr = next(self.generator) + except StopIteration: + s.wr(self.req.stb, 0) + if not s.rd(self.req.lock): + s.interrupt = True + print("data ack count: {0}".format(self.dat_ack_cnt)) + return + s.wr(self.req.adr, adr) + s.wr(self.req.we, we) + s.wr(self.req.stb, 1) + +def main(): + sim = Simulator(TB(), TopLevel("my.vcd")) + sim.run() + +main() diff --git a/tb/asmicon/common.py b/tb/lasmicon/common.py similarity index 55% rename from tb/asmicon/common.py rename to tb/lasmicon/common.py index b41956c3..e7e63e17 100644 --- a/tb/asmicon/common.py +++ b/tb/lasmicon/common.py @@ -4,7 +4,7 @@ from math import ceil from migen.fhdl.std import * from migen.sim.generic import Proxy -from milkymist import asmicon +from milkymist import lasmicon MHz = 1000000 clk_freq = (83 + Fraction(1, 3))*MHz @@ -15,28 +15,31 @@ def ns(t, margin=True): t += clk_period_ns/2 return ceil(t/clk_period_ns) -sdram_phy = asmicon.PhySettings( +sdram_phy = lasmicon.PhySettings( + type="DDR", dfi_d=64, nphases=2, rdphase=0, - wrphase=1 + wrphase=1, + cl=3 ) -sdram_geom = asmicon.GeomSettings( +sdram_geom = lasmicon.GeomSettings( bank_a=2, row_a=13, col_a=10 ) -sdram_timing = asmicon.TimingSettings( +sdram_timing = lasmicon.TimingSettings( tRP=ns(15), tRCD=ns(15), tWR=ns(15), + tWTR=2, tREFI=ns(7800, False), tRFC=ns(70), - CL=3, - rd_delay=4, + read_latency=5, + write_latency=0, - slot_time=16, + req_queue_size=8, read_time=32, write_time=16 ) @@ -69,10 +72,11 @@ def decode_sdram(ras_n, cas_n, we_n, bank, address): elts.append("LMR") return elts -class CommandLogger: +class CommandLogger(Module): def __init__(self, cmd, rw=False): self.cmd = cmd - self.rw = rw + if rw: + self.comb += self.cmd.ack.eq(1) def do_simulation(self, s): elts = ["@" + str(s.cycle_counter)] @@ -80,15 +84,8 @@ class CommandLogger: elts += decode_sdram(cmdp.ras_n, cmdp.cas_n, cmdp.we_n, cmdp.ba, cmdp.a) if len(elts) > 1: print("\t".join(elts)) - - def get_fragment(self): - if self.rw: - comb = [self.cmd.ack.eq(1)] - else: - comb = [] - return Fragment(comb, sim=[self.do_simulation]) -class DFILogger: +class DFILogger(Module): def __init__(self, dfi): self.dfi = dfi @@ -96,35 +93,7 @@ class DFILogger: dfip = Proxy(s, self.dfi) for i, p in enumerate(dfip.phases): - elts = ["PH=" + str(i) + "\t @" + str(s.cycle_counter)] + elts = ["@" + str(s.cycle_counter) + ":" + str(i)] elts += decode_sdram(p.ras_n, p.cas_n, p.we_n, p.bank, p.address) if len(elts) > 1: print("\t".join(elts)) - - 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]) diff --git a/tb/lasmicon/lasmicon.py b/tb/lasmicon/lasmicon.py new file mode 100644 index 00000000..e64ece39 --- /dev/null +++ b/tb/lasmicon/lasmicon.py @@ -0,0 +1,45 @@ +from migen.fhdl.std import * +from migen.bus.lasmibus import * +from migen.sim.generic import Simulator, TopLevel + +from milkymist.lasmicon import * + +from common import sdram_phy, sdram_geom, sdram_timing, DFILogger + +def my_generator_r(n): + for x in range(10): + t = TRead(128*n + 48*n*x) + yield t + print("{0:3}: reads done".format(n)) + +def my_generator_w(n): + for x in range(10): + t = TWrite(128*n + 48*n*x, x) + yield t + print("{0:3}: writes done".format(n)) + +def my_generator(n): + if n % 2: + return my_generator_w(n // 2) + else: + return my_generator_r(n // 2) + +class TB(Module): + def __init__(self): + self.submodules.dut = LASMIcon(sdram_phy, sdram_geom, sdram_timing) + self.submodules.xbar = lasmibus.Crossbar([self.dut.lasmic], 6, self.dut.nrowbits) + self.submodules.logger = DFILogger(self.dut.dfi) + + self.initiators = [Initiator(my_generator(n), master) + for n, master in enumerate(self.xbar.masters)] + self.submodules += self.initiators + + def do_simulation(self, s): + s.interrupt = all(initiator.done for initiator in self.initiators) + + +def main(): + sim = Simulator(TB(), TopLevel("my.vcd")) + sim.run() + +main() diff --git a/tb/lasmicon/lasmicon_wb.py b/tb/lasmicon/lasmicon_wb.py new file mode 100644 index 00000000..4d6e2476 --- /dev/null +++ b/tb/lasmicon/lasmicon_wb.py @@ -0,0 +1,43 @@ +from migen.fhdl.std import * +from migen.bus import wishbone, wishbone2lasmi, lasmibus +from migen.bus.transactions import * +from migen.sim.generic import Simulator, TopLevel + +from milkymist.lasmicon import * + +from common import sdram_phy, sdram_geom, sdram_timing, DFILogger + +l2_size = 8192 # in bytes + +def my_generator(): + for x in range(20): + t = TWrite(x, x) + yield t + print(str(t) + " delay=" + str(t.latency)) + for x in range(20): + t = TRead(x) + yield t + print(str(t) + " delay=" + str(t.latency)) + for x in range(20): + t = TRead(x+l2_size//4) + yield t + print(str(t) + " delay=" + str(t.latency)) + +class TB(Module): + def __init__(self): + self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing) + # FIXME: remove dummy master + self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], 2, self.ctler.nrowbits) + self.submodules.logger = DFILogger(self.ctler.dfi) + self.submodules.bridge = wishbone2lasmi.WB2LASMI(l2_size//4, self.xbar.masters[0]) + self.submodules.initiator = wishbone.Initiator(my_generator()) + self.submodules.conn = wishbone.InterconnectPointToPoint(self.initiator.bus, self.bridge.wishbone) + + def do_simulation(self, s): + s.interrupt = self.initiator.done + +def main(): + sim = Simulator(TB(), TopLevel("my.vcd")) + sim.run() + +main() diff --git a/tb/asmicon/refresher.py b/tb/lasmicon/refresher.py similarity index 68% rename from tb/asmicon/refresher.py rename to tb/lasmicon/refresher.py index 79b9b189..72a527a3 100644 --- a/tb/asmicon/refresher.py +++ b/tb/lasmicon/refresher.py @@ -3,11 +3,11 @@ from random import Random from migen.fhdl.std import * from migen.sim.generic import Simulator, TopLevel -from milkymist.asmicon.refresher import * +from milkymist.lasmicon.refresher import * from common import CommandLogger -class Granter: +class Granter(Module): def __init__(self, req, ack): self.req = req self.ack = ack @@ -34,16 +34,14 @@ class Granter: if len(elts) > 1: print("\t".join(elts)) - - def get_fragment(self): - return Fragment(sim=[self.do_simulation]) + +class TB(Module): + def __init__(self): + self.submodules.dut = Refresher(13, 2, tRP=3, tREFI=100, tRFC=5) + self.submodules.logger = CommandLogger(self.dut.cmd) + self.submodules.granter = Granter(self.dut.req, self.dut.ack) def main(): - dut = Refresher(13, 2, tRP=3, tREFI=100, tRFC=5) - logger = CommandLogger(dut.cmd) - granter = Granter(dut.req, dut.ack) - fragment = dut.get_fragment() + logger.get_fragment() + granter.get_fragment() - sim = Simulator(fragment) - sim.run(400) + Simulator(TB()).run(400) main() -- 2.30.2