From: Sebastien Bourdeauducq Date: Sun, 10 Mar 2013 18:32:38 +0000 (+0100) Subject: Use new module, autoreg and eventmanager Migen APIs X-Git-Tag: 24jan2021_ls180~3034 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a9b723568a7d5b84859687a07b8283e22b12ea39;p=litex.git Use new module, autoreg and eventmanager Migen APIs --- diff --git a/common/csrbase.h b/common/csrbase.h index 89b730dc..c9f7b1a3 100644 --- a/common/csrbase.h +++ b/common/csrbase.h @@ -1,12 +1,12 @@ #ifndef __CSRBASE_H #define __CSRBASE_H -#define UART_BASE 0xe0000000 -#define DFII_BASE 0xe0000800 -#define ID_BASE 0xe0001000 -#define TIMER0_BASE 0xe0001800 -#define MINIMAC_BASE 0xe0002000 -#define FB_BASE 0xe0002800 -#define ASMIPROBE_BASE 0xe0003000 +#define UART_BASE 0xe0000000 +#define DFII_BASE 0xe0000800 +#define IDENTIFIER_BASE 0xe0001000 +#define TIMER0_BASE 0xe0001800 +#define MINIMAC_BASE 0xe0002000 +#define FB_BASE 0xe0002800 +#define ASMIPROBE_BASE 0xe0003000 #endif /* __CSRBASE_H */ diff --git a/milkymist/asmicon/__init__.py b/milkymist/asmicon/__init__.py index 9f93a5e1..828ccd64 100644 --- a/milkymist/asmicon/__init__.py +++ b/milkymist/asmicon/__init__.py @@ -1,4 +1,5 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bus import dfi, asmibus from milkymist.asmicon.refresher import * @@ -34,13 +35,12 @@ class TimingSettings: self.write_time = write_time self.slot_time = slot_time -class ASMIcon: +class ASMIcon(Module): def __init__(self, phy_settings, geom_settings, timing_settings, full_selector=False): self.phy_settings = phy_settings self.geom_settings = geom_settings self.timing_settings = timing_settings self.full_selector = full_selector - self.finalized = False self.dfi = dfi.Interface(self.geom_settings.mux_a, self.geom_settings.bank_a, @@ -50,26 +50,14 @@ class ASMIcon: self.address_align = log2_int(burst_length) aw = self.geom_settings.bank_a + self.geom_settings.row_a + self.geom_settings.col_a - self.address_align dw = self.phy_settings.dfi_d*self.phy_settings.nphases - self.hub = asmibus.Hub(aw, dw, self.timing_settings.slot_time) + self.submodules.hub = asmibus.Hub(aw, dw, self.timing_settings.slot_time) - def finalize(self): - if self.finalized: - raise FinalizeError - self.finalized = True - self.hub.finalize() + def do_finalize(self): slots = self.hub.get_slots() - self.refresher = Refresher(self.geom_settings.mux_a, self.geom_settings.bank_a, + self.submodules.refresher = Refresher(self.geom_settings.mux_a, self.geom_settings.bank_a, self.timing_settings.tRP, self.timing_settings.tREFI, self.timing_settings.tRFC) - self.bank_machines = [BankMachine(self.geom_settings, self.timing_settings, self.address_align, i, slots, self.full_selector) + self.submodules.bank_machines = [BankMachine(self.geom_settings, self.timing_settings, self.address_align, i, slots, self.full_selector) for i in range(2**self.geom_settings.bank_a)] - self.multiplexer = Multiplexer(self.phy_settings, self.geom_settings, self.timing_settings, + self.submodules.multiplexer = Multiplexer(self.phy_settings, self.geom_settings, self.timing_settings, self.bank_machines, self.refresher, self.dfi, self.hub) - - def get_fragment(self): - if not self.finalized: - raise FinalizeError - return self.hub.get_fragment() + \ - self.refresher.get_fragment() + \ - sum([bm.get_fragment() for bm in self.bank_machines], Fragment()) + \ - self.multiplexer.get_fragment() diff --git a/milkymist/asmicon/bankmachine.py b/milkymist/asmicon/bankmachine.py index 07244e97..0e296fb0 100644 --- a/milkymist/asmicon/bankmachine.py +++ b/milkymist/asmicon/bankmachine.py @@ -1,4 +1,5 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bus.asmibus import * from migen.genlib.roundrobin import * from migen.genlib.fsm import FSM @@ -33,97 +34,81 @@ class _AddressSlicer: else: return Cat(Replicate(0, self.address_align), address[:self._b1]) -class _Selector: +class _Selector(Module): def __init__(self, slicer, bankn, slots): - self.slicer = slicer - self.bankn = bankn - self.slots = slots - - self.nslots = len(self.slots) + nslots = len(slots) self.stb = Signal() self.ack = Signal() - self.tag = Signal(max=self.nslots) - self.adr = Signal(self.slots[0].adr.nbits) + self.tag = Signal(max=nslots) + self.adr = Signal(slots[0].adr.nbits) self.we = Signal() # derived classes should drive rr.request - self.rr = RoundRobin(self.nslots, SP_CE) + self.submodules.rr = RoundRobin(nslots, SP_CE) - def get_fragment(self): - comb = [] - rr = self.rr - + ### + # Multiplex + rr = self.rr state = Signal(2) - comb += [ - state.eq(Array(slot.state for slot in self.slots)[rr.grant]), - self.adr.eq(Array(slot.adr for slot in self.slots)[rr.grant]), - self.we.eq(Array(slot.we for slot in self.slots)[rr.grant]), + self.comb += [ + state.eq(Array(slot.state for slot in slots)[rr.grant]), + self.adr.eq(Array(slot.adr for slot in slots)[rr.grant]), + self.we.eq(Array(slot.we for slot in slots)[rr.grant]), self.stb.eq( - (self.slicer.bank(self.adr) == self.bankn) \ + (slicer.bank(self.adr) == bankn) \ & (state == SLOT_PENDING)), rr.ce.eq(self.ack | ~self.stb), self.tag.eq(rr.grant) ] - comb += [If((rr.grant == i) & self.stb & self.ack, slot.process.eq(1)) - for i, slot in enumerate(self.slots)] - - return Fragment(comb) + rr.get_fragment() + self.comb += [If((rr.grant == i) & self.stb & self.ack, slot.process.eq(1)) + for i, slot in enumerate(slots)] + + self.complete_selector(slicer, bankn, slots) class _SimpleSelector(_Selector): - def get_fragment(self): - comb = [] - for i, slot in enumerate(self.slots): - comb.append(self.rr.request[i].eq( - (self.slicer.bank(slot.adr) == self.bankn) & \ - (slot.state == SLOT_PENDING) - )) - - return Fragment(comb) + _Selector.get_fragment(self) + def complete_selector(self, slicer, bankn, slots): + for i, slot in enumerate(slots): + self.comb += self.rr.request[i].eq( + (slicer.bank(slot.adr) == bankn) & \ + (slot.state == SLOT_PENDING)) class _FullSelector(_Selector): - def get_fragment(self): - comb = [] - sync = [] + def complete_selector(self, slicer, bankn, slots): rr = self.rr # List outstanding requests for our bank outstandings = [] - for slot in self.slots: + for slot in slots: outstanding = Signal() - comb.append(outstanding.eq( - (self.slicer.bank(slot.adr) == self.bankn) & \ - (slot.state == SLOT_PENDING) - )) + self.comb += outstanding.eq( + (slicer.bank(slot.adr) == bankn) & \ + (slot.state == SLOT_PENDING)) outstandings.append(outstanding) # Row tracking - openrow_r = Signal(self.slicer.geom_settings.row_a) - openrow_n = Signal(self.slicer.geom_settings.row_a) - openrow = Signal(self.slicer.geom_settings.row_a) - comb += [ - openrow_n.eq(self.slicer.row(self.adr)), + openrow_r = Signal(slicer.geom_settings.row_a) + openrow_n = Signal(slicer.geom_settings.row_a) + openrow = Signal(slicer.geom_settings.row_a) + self.comb += [ + openrow_n.eq(slicer.row(self.adr)), If(self.stb, openrow.eq(openrow_n) ).Else( openrow.eq(openrow_r) ) ] - sync += [ - If(self.stb & self.ack, - openrow_r.eq(openrow_n) - ) - ] + self.sync += If(self.stb & self.ack, openrow_r.eq(openrow_n)) hits = [] - for slot, os in zip(self.slots, outstandings): + for slot, os in zip(slots, outstandings): hit = Signal() - comb.append(hit.eq((self.slicer.row(slot.adr) == openrow) & os)) + self.comb += hit.eq((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))) + self.comb += has_hit.eq(optree("|", hits)) best_hit = [rr.request[i].eq(hit) for i, hit in enumerate(hits)] @@ -135,84 +120,72 @@ class _FullSelector(_Selector): *best_fallback ) - if self.slots[0].time: + if slots[0].time: # Implement anti-starvation timer matures = [] - for slot, os in zip(self.slots, outstandings): + for slot, os in zip(slots, outstandings): mature = Signal() comb.append(mature.eq(slot.mature & os)) matures.append(mature) has_mature = Signal() - comb.append(has_mature.eq(optree("|", matures))) + self.comb += 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) - - return Fragment(comb, sync) + _Selector.get_fragment(self) + self.comb += select_stmt -class _Buffer: +class _Buffer(Module): def __init__(self, source): - self.source = source - self.stb = Signal() self.ack = Signal() - self.tag = Signal(self.source.tag.bv) - self.adr = Signal(self.source.adr.bv) + self.tag = Signal(source.tag.bv) + self.adr = Signal(source.adr.bv) self.we = Signal() - def get_fragment(self): + ### + en = Signal() - comb = [ + self.comb += [ en.eq(self.ack | ~self.stb), - self.source.ack.eq(en) + source.ack.eq(en) ] - sync = [ + self.sync += [ If(en, - self.stb.eq(self.source.stb), - self.tag.eq(self.source.tag), - self.adr.eq(self.source.adr), - self.we.eq(self.source.we) + self.stb.eq(source.stb), + self.tag.eq(source.tag), + self.adr.eq(source.adr), + self.we.eq(source.we) ) ] - return Fragment(comb, sync) -class BankMachine: +class BankMachine(Module): def __init__(self, geom_settings, timing_settings, address_align, bankn, slots, full_selector): - self.geom_settings = geom_settings - self.timing_settings = timing_settings - self.address_align = address_align - self.bankn = bankn - self.slots = slots - self.full_selector = full_selector - self.refresh_req = Signal() self.refresh_gnt = Signal() self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a, bits_for(len(slots)-1)) - def get_fragment(self): - comb = [] - sync = [] - + ### + # Sub components - slicer = _AddressSlicer(self.geom_settings, self.address_align) - if self.full_selector: - selector = _FullSelector(slicer, self.bankn, self.slots) - buf = _Buffer(selector) - cmdsource = buf + slicer = _AddressSlicer(geom_settings, address_align) + if full_selector: + selector = _FullSelector(slicer, bankn, slots) + self.submodules.buf = _Buffer(selector) + cmdsource = self.buf else: - selector = _SimpleSelector(slicer, self.bankn, self.slots) + selector = _SimpleSelector(slicer, bankn, slots) cmdsource = selector + self.submodules += selector # Row tracking has_openrow = Signal() - openrow = Signal(self.geom_settings.row_a) + openrow = Signal(geom_settings.row_a) hit = Signal() - comb.append(hit.eq(openrow == slicer.row(cmdsource.adr))) + self.comb += hit.eq(openrow == slicer.row(cmdsource.adr)) track_open = Signal() track_close = Signal() - sync += [ + self.sync += [ If(track_open, has_openrow.eq(1), openrow.eq(slicer.row(cmdsource.adr)) @@ -224,8 +197,8 @@ class BankMachine: # Address generation s_row_adr = Signal() - comb += [ - self.cmd.ba.eq(self.bankn), + self.comb += [ + self.cmd.ba.eq(bankn), If(s_row_adr, self.cmd.a.eq(slicer.row(cmdsource.adr)) ).Else( @@ -233,14 +206,14 @@ class BankMachine: ) ] - comb.append(self.cmd.tag.eq(cmdsource.tag)) + self.comb += self.cmd.tag.eq(cmdsource.tag) # Respect write-to-precharge specification precharge_ok = Signal() - t_unsafe_precharge = 2 + self.timing_settings.tWR - 1 + t_unsafe_precharge = 2 + timing_settings.tWR - 1 unsafe_precharge_count = Signal(max=t_unsafe_precharge+1) - comb.append(precharge_ok.eq(unsafe_precharge_count == 0)) - sync += [ + self.comb += precharge_ok.eq(unsafe_precharge_count == 0) + self.sync += [ If(self.cmd.stb & self.cmd.ack & self.cmd.is_write, unsafe_precharge_count.eq(t_unsafe_precharge) ).Elif(~precharge_ok, @@ -250,9 +223,10 @@ class BankMachine: # Control and command generation FSM fsm = FSM("REGULAR", "PRECHARGE", "ACTIVATE", "REFRESH", delayed_enters=[ - ("TRP", "ACTIVATE", self.timing_settings.tRP-1), - ("TRCD", "REGULAR", self.timing_settings.tRCD-1) + ("TRP", "ACTIVATE", timing_settings.tRP-1), + ("TRCD", "REGULAR", timing_settings.tRCD-1) ]) + self.submodules += fsm fsm.act(fsm.REGULAR, If(self.refresh_req, fsm.next_state(fsm.REFRESH) @@ -298,12 +272,3 @@ class BankMachine: track_close.eq(1), If(~self.refresh_req, fsm.next_state(fsm.REGULAR)) ) - - if self.full_selector: - buf_fragment = buf.get_fragment() - else: - buf_fragment = Fragment() - return Fragment(comb, sync) + \ - selector.get_fragment() + \ - buf_fragment + \ - fsm.get_fragment() diff --git a/milkymist/asmicon/multiplexer.py b/milkymist/asmicon/multiplexer.py index 0f257841..ae254418 100644 --- a/milkymist/asmicon/multiplexer.py +++ b/milkymist/asmicon/multiplexer.py @@ -1,4 +1,5 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.genlib.roundrobin import * from migen.genlib.misc import optree from migen.genlib.fsm import FSM @@ -20,171 +21,141 @@ class CommandRequestRW(CommandRequest): self.is_write = Signal() self.tag = Signal(tagbits) -class _CommandChooser: +class _CommandChooser(Module): def __init__(self, requests, tagbits): - self.requests = requests - self.want_reads = Signal() self.want_writes = Signal() # NB: cas_n/ras_n/we_n are 1 when stb is inactive - self.cmd = CommandRequestRW(len(self.requests[0].a), len(self.requests[0].ba), tagbits) + self.cmd = CommandRequestRW(len(requests[0].a), len(requests[0].ba), tagbits) - def get_fragment(self): - comb = [] - sync = [] - - rr = RoundRobin(len(self.requests), SP_CE) + ### + + rr = RoundRobin(len(requests), SP_CE) + self.submodules += rr - comb += [rr.request[i].eq(req.stb & ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))) - for i, req in enumerate(self.requests)] + self.comb += [rr.request[i].eq(req.stb & ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))) + for i, req in enumerate(requests)] stb = Signal() - comb.append(stb.eq(Array(req.stb for req in self.requests)[rr.grant])) + self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant]) for name in ["a", "ba", "is_read", "is_write", "tag"]: - choices = Array(getattr(req, name) for req in self.requests) - comb.append(getattr(self.cmd, name).eq(choices[rr.grant])) + choices = Array(getattr(req, name) for req in requests) + self.comb += getattr(self.cmd, name).eq(choices[rr.grant]) for name in ["cas_n", "ras_n", "we_n"]: # we should only assert those signals when stb is 1 - choices = Array(getattr(req, name) for req in self.requests) - comb.append(If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))) - comb.append(self.cmd.stb.eq(stb \ + choices = Array(getattr(req, name) for req in requests) + self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant])) + self.comb += self.cmd.stb.eq(stb \ & (self.cmd.is_read == self.want_reads) \ - & (self.cmd.is_write == self.want_writes))) + & (self.cmd.is_write == self.want_writes)) - comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1)) - for i, req in enumerate(self.requests)] - comb.append(rr.ce.eq(self.cmd.ack)) - - return Fragment(comb, sync) + rr.get_fragment() + self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1)) + for i, req in enumerate(requests)] + self.comb += rr.ce.eq(self.cmd.ack) -class _Steerer: +class _Steerer(Module): def __init__(self, commands, dfi): - self.commands = commands - self.dfi = dfi - - ncmd = len(self.commands) - nph = len(self.dfi.phases) + ncmd = len(commands) + nph = len(dfi.phases) self.sel = [Signal(max=ncmd) for i in range(nph)] - def get_fragment(self): - comb = [] - sync = [] + ### + def stb_and(cmd, attr): if not hasattr(cmd, "stb"): return 0 else: return cmd.stb & getattr(cmd, attr) - for phase, sel in zip(self.dfi.phases, self.sel): - comb += [ + for phase, sel in zip(dfi.phases, self.sel): + self.comb += [ phase.cke.eq(1), phase.cs_n.eq(0) ] - sync += [ - phase.address.eq(Array(cmd.a for cmd in self.commands)[sel]), - phase.bank.eq(Array(cmd.ba for cmd in self.commands)[sel]), - phase.cas_n.eq(Array(cmd.cas_n for cmd in self.commands)[sel]), - phase.ras_n.eq(Array(cmd.ras_n for cmd in self.commands)[sel]), - phase.we_n.eq(Array(cmd.we_n for cmd in self.commands)[sel]), - phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in self.commands)[sel]), - phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in self.commands)[sel]) + self.sync += [ + phase.address.eq(Array(cmd.a for cmd in commands)[sel]), + phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]), + phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]), + phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]), + phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]), + phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]), + phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel]) ] - return Fragment(comb, sync) -class _Datapath: +class _Datapath(Module): def __init__(self, timing_settings, command, dfi, hub): - self.timing_settings = timing_settings - self.command = command - self.dfi = dfi - self.hub = hub - - def get_fragment(self): - comb = [] - sync = [] - tagbits = len(self.hub.tag_call) + tagbits = len(hub.tag_call) rd_valid = Signal() rd_tag = Signal(tagbits) wr_valid = Signal() wr_tag = Signal(tagbits) - comb += [ - self.hub.call.eq(rd_valid | wr_valid), + self.comb += [ + hub.call.eq(rd_valid | wr_valid), If(wr_valid, - self.hub.tag_call.eq(wr_tag) + hub.tag_call.eq(wr_tag) ).Else( - self.hub.tag_call.eq(rd_tag) + hub.tag_call.eq(rd_tag) ) ] - rd_delay = self.timing_settings.rd_delay + 1 + rd_delay = timing_settings.rd_delay + 1 rd_valid_d = [Signal() for i in range(rd_delay)] rd_tag_d = [Signal(tagbits) for i in range(rd_delay)] for i in range(rd_delay): if i: - sync += [ + self.sync += [ rd_valid_d[i].eq(rd_valid_d[i-1]), rd_tag_d[i].eq(rd_tag_d[i-1]) ] else: - sync += [ - rd_valid_d[i].eq(self.command.stb & self.command.ack & self.command.is_read), - rd_tag_d[i].eq(self.command.tag) + self.sync += [ + rd_valid_d[i].eq(command.stb & command.ack & command.is_read), + rd_tag_d[i].eq(command.tag) ] - comb += [ + self.comb += [ rd_valid.eq(rd_valid_d[-1]), rd_tag.eq(rd_tag_d[-1]), - wr_valid.eq(self.command.stb & self.command.ack & self.command.is_write), - wr_tag.eq(self.command.tag), + wr_valid.eq(command.stb & command.ack & command.is_write), + wr_tag.eq(command.tag), ] - all_rddata = [p.rddata for p in self.dfi.phases] - all_wrdata = [p.wrdata for p in self.dfi.phases] - all_wrdata_mask = [p.wrdata_mask for p in self.dfi.phases] - comb += [ - self.hub.dat_r.eq(Cat(*all_rddata)), - Cat(*all_wrdata).eq(self.hub.dat_w), - Cat(*all_wrdata_mask).eq(self.hub.dat_wm) + all_rddata = [p.rddata for p in dfi.phases] + all_wrdata = [p.wrdata for p in dfi.phases] + all_wrdata_mask = [p.wrdata_mask for p in dfi.phases] + self.comb += [ + hub.dat_r.eq(Cat(*all_rddata)), + Cat(*all_wrdata).eq(hub.dat_w), + Cat(*all_wrdata_mask).eq(hub.dat_wm) ] - - return Fragment(comb, sync) -class Multiplexer: +class Multiplexer(Module): def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, hub): - self.phy_settings = phy_settings - self.geom_settings = geom_settings - self.timing_settings = timing_settings - self.bank_machines = bank_machines - self.refresher = refresher - self.dfi = dfi - self.hub = hub - - assert(self.phy_settings.nphases == len(dfi.phases)) - if self.phy_settings.nphases != 2: + assert(phy_settings.nphases == len(dfi.phases)) + if phy_settings.nphases != 2: raise NotImplementedError("TODO: multiplexer only supports 2 phases") - def get_fragment(self): - comb = [] - sync = [] - # Command choosing - requests = [bm.cmd for bm in self.bank_machines] - tagbits = len(self.hub.tag_call) + requests = [bm.cmd for bm in bank_machines] + tagbits = len(hub.tag_call) choose_cmd = _CommandChooser(requests, tagbits) choose_req = _CommandChooser(requests, tagbits) - comb += [ + self.comb += [ choose_cmd.want_reads.eq(0), choose_cmd.want_writes.eq(0) ] + self.submodules += choose_cmd, choose_req # Command steering - nop = CommandRequest(self.geom_settings.mux_a, self.geom_settings.bank_a) - commands = [nop, choose_cmd.cmd, choose_req.cmd, self.refresher.cmd] # nop must be 1st + nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a) + commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4) - steerer = _Steerer(commands, self.dfi) + steerer = _Steerer(commands, dfi) + self.submodules += steerer # Read/write turnaround read_available = Signal() write_available = Signal() - comb += [ + self.comb += [ read_available.eq(optree("|", [req.stb & req.is_read for req in requests])), write_available.eq(optree("|", [req.stb & req.is_write for req in requests])) ] @@ -195,42 +166,40 @@ class Multiplexer: if timeout: t = timeout - 1 time = Signal(max=t+1) - comb.append(max_time.eq(time == 0)) - sync.append( - If(~en, + self.comb += max_time.eq(time == 0) + self.sync += If(~en, time.eq(t) ).Elif(~max_time, time.eq(time - 1) ) - ) else: - comb.append(max_time.eq(0)) + self.comb += max_time.eq(0) return en, max_time - read_time_en, max_read_time = anti_starvation(self.timing_settings.read_time) - write_time_en, max_write_time = anti_starvation(self.timing_settings.write_time) + read_time_en, max_read_time = anti_starvation(timing_settings.read_time) + write_time_en, max_write_time = anti_starvation(timing_settings.write_time) # Refresh - comb += [bm.refresh_req.eq(self.refresher.req) - for bm in self.bank_machines] + self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines] go_to_refresh = Signal() - comb.append(go_to_refresh.eq( - optree("&", [bm.refresh_gnt for bm in self.bank_machines]))) + self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines])) # Datapath - datapath = _Datapath(self.timing_settings, choose_req.cmd, self.dfi, self.hub) + datapath = _Datapath(timing_settings, choose_req.cmd, dfi, hub) + self.submodules += datapath # Control FSM fsm = FSM("READ", "WRITE", "REFRESH", delayed_enters=[ - ("RTW", "WRITE", self.timing_settings.rd_delay), - ("WTR", "READ", self.timing_settings.tWR) + ("RTW", "WRITE", timing_settings.rd_delay), + ("WTR", "READ", timing_settings.tWR) ]) + self.submodules += fsm fsm.act(fsm.READ, read_time_en.eq(1), choose_req.want_reads.eq(1), choose_cmd.cmd.ack.eq(1), choose_req.cmd.ack.eq(1), - steerer.sel[1-self.phy_settings.rdphase].eq(STEER_CMD), - steerer.sel[self.phy_settings.rdphase].eq(STEER_REQ), + steerer.sel[1-phy_settings.rdphase].eq(STEER_CMD), + steerer.sel[phy_settings.rdphase].eq(STEER_REQ), If(write_available, # TODO: switch only after several cycles of ~read_available? If(~read_available | max_read_time, fsm.next_state(fsm.RTW)) @@ -242,8 +211,8 @@ class Multiplexer: choose_req.want_writes.eq(1), choose_cmd.cmd.ack.eq(1), choose_req.cmd.ack.eq(1), - steerer.sel[1-self.phy_settings.wrphase].eq(STEER_CMD), - steerer.sel[self.phy_settings.wrphase].eq(STEER_REQ), + steerer.sel[1-phy_settings.wrphase].eq(STEER_CMD), + steerer.sel[phy_settings.wrphase].eq(STEER_REQ), If(read_available, If(~write_available | max_write_time, fsm.next_state(fsm.WTR)) ), @@ -251,14 +220,7 @@ class Multiplexer: ) fsm.act(fsm.REFRESH, steerer.sel[0].eq(STEER_REFRESH), - If(~self.refresher.req, fsm.next_state(fsm.READ)) + If(~refresher.req, fsm.next_state(fsm.READ)) ) # FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog - comb.append(self.refresher.ack.eq(fsm._state == fsm.REFRESH)) - - return Fragment(comb, sync) + \ - choose_cmd.get_fragment() + \ - choose_req.get_fragment() + \ - steerer.get_fragment() + \ - datapath.get_fragment() + \ - fsm.get_fragment() + self.comb += refresher.ack.eq(fsm._state == fsm.REFRESH) diff --git a/milkymist/asmicon/refresher.py b/milkymist/asmicon/refresher.py index 641bb232..3ad0334b 100644 --- a/milkymist/asmicon/refresher.py +++ b/milkymist/asmicon/refresher.py @@ -1,28 +1,23 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.genlib.misc import timeline from migen.genlib.fsm import FSM from milkymist.asmicon.multiplexer import * -class Refresher: +class Refresher(Module): def __init__(self, a, ba, tRP, tREFI, tRFC): - self.tRP = tRP - self.tREFI = tREFI - self.tRFC = tRFC - self.req = Signal() self.ack = Signal() # 1st command 1 cycle after assertion of ack self.cmd = CommandRequest(a, ba) - def get_fragment(self): - comb = [] - sync = [] - + ### + # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() - sync += [ + self.sync += [ self.cmd.a.eq(2**10), self.cmd.ba.eq(0), self.cmd.cas_n.eq(1), @@ -30,28 +25,28 @@ class Refresher: self.cmd.we_n.eq(1), seq_done.eq(0) ] - sync += timeline(seq_start, [ + self.sync += timeline(seq_start, [ (1, [ self.cmd.ras_n.eq(0), self.cmd.we_n.eq(0) ]), - (1+self.tRP, [ + (1+tRP, [ self.cmd.cas_n.eq(0), self.cmd.ras_n.eq(0) ]), - (1+self.tRP+self.tRFC, [ + (1+tRP+tRFC, [ seq_done.eq(1) ]) ]) # Periodic refresh counter - counter = Signal(max=self.tREFI) + counter = Signal(max=tREFI) start = Signal() - sync += [ + self.sync += [ start.eq(0), If(counter == 0, start.eq(1), - counter.eq(self.tREFI - 1) + counter.eq(tREFI - 1) ).Else( counter.eq(counter - 1) ) @@ -59,6 +54,7 @@ class Refresher: # Control FSM fsm = FSM("IDLE", "WAIT_GRANT", "WAIT_SEQ") + self.submodules += fsm fsm.act(fsm.IDLE, If(start, fsm.next_state(fsm.WAIT_GRANT))) fsm.act(fsm.WAIT_GRANT, self.req.eq(1), @@ -71,5 +67,3 @@ class Refresher: self.req.eq(1), If(seq_done, fsm.next_state(fsm.IDLE)) ) - - return Fragment(comb, sync) + fsm.get_fragment() diff --git a/milkymist/asmiprobe/__init__.py b/milkymist/asmiprobe/__init__.py index 014740e9..69844850 100644 --- a/milkymist/asmiprobe/__init__.py +++ b/milkymist/asmiprobe/__init__.py @@ -1,36 +1,33 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bank.description import * -from migen.bank import csrgen -class ASMIprobe: - def __init__(self, address, hub, trace_depth=16): - self.hub = hub - self.trace_depth = trace_depth - - slot_count = len(self.hub.get_slots()) - assert(self.trace_depth < 256) +class ASMIprobe(Module): + def __init__(self, hub, trace_depth=16): + slots = hub.get_slots() + slot_count = len(slots) + assert(trace_depth < 256) assert(slot_count < 256) self._slot_count = RegisterField("slot_count", 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY) self._trace_depth = RegisterField("trace_depth", 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY) - self._slot_status = [RegisterField("slot_status", 2, access_bus=READ_ONLY, access_dev=WRITE_ONLY) + self._slot_status = [RegisterField("slot_status" + str(i), 2, access_bus=READ_ONLY, access_dev=WRITE_ONLY) for i in range(slot_count)] - self._trace = [RegisterField("trace", 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY) - for i in range(self.trace_depth)] + self._trace = [RegisterField("trace" + str(i), 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY) + for i in range(trace_depth)] - self.bank = csrgen.Bank([self._slot_count, self._trace_depth] - + self._slot_status + self._trace, address=address) - - def get_fragment(self): - slots = self.hub.get_slots() - comb = [ - self._slot_count.field.w.eq(len(slots)), - self._trace_depth.field.w.eq(self.trace_depth) + ### + + self.comb += [ + self._slot_count.field.w.eq(slot_count), + self._trace_depth.field.w.eq(trace_depth) ] for slot, status in zip(slots, self._slot_status): - comb.append(status.field.w.eq(slot.state)) + self.comb += status.field.w.eq(slot.state) shift_tags = [self._trace[n].field.w.eq(self._trace[n+1].field.w) for n in range(len(self._trace) - 1)] - shift_tags.append(self._trace[-1].field.w.eq(self.hub.tag_call)) - sync = [If(self.hub.call, *shift_tags)] - return Fragment(comb, sync) + self.bank.get_fragment() + shift_tags.append(self._trace[-1].field.w.eq(hub.tag_call)) + self.sync += If(hub.call, *shift_tags) + + def get_registers(self): + return [self._slot_count, self._trace_depth] + self._slot_status + self._trace diff --git a/milkymist/dfii/__init__.py b/milkymist/dfii/__init__.py index cedca621..dc71c820 100644 --- a/milkymist/dfii/__init__.py +++ b/milkymist/dfii/__init__.py @@ -1,12 +1,10 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bus import dfi from migen.bank.description import * -from migen.bank import csrgen -class PhaseInjector: +class PhaseInjector(Module, AutoReg): def __init__(self, phase): - self.phase = phase - self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY) self._we = Field("we", 1, WRITE_ONLY, READ_ONLY) self._cas = Field("cas", 1, WRITE_ONLY, READ_ONLY) @@ -17,45 +15,38 @@ class PhaseInjector: [self._cs, self._we, self._cas, self._ras, self._wren, self._rden]) self._command_issue = RegisterRaw("command_issue") - self._address = RegisterField("address", len(self.phase.address)) - self._baddress = RegisterField("baddress", len(self.phase.bank)) + self._address = RegisterField("address", len(phase.address)) + self._baddress = RegisterField("baddress", len(phase.bank)) - self._wrdata = RegisterField("wrdata", len(self.phase.wrdata)) - self._rddata = RegisterField("rddata", len(self.phase.rddata), READ_ONLY, WRITE_ONLY) + self._wrdata = RegisterField("wrdata", len(phase.wrdata)) + self._rddata = RegisterField("rddata", len(phase.rddata), READ_ONLY, WRITE_ONLY) - def get_registers(self): - return [self._command, self._command_issue, - self._address, self._baddress, - self._wrdata, self._rddata] - - def get_fragment(self): - comb = [ + ### + + self.comb += [ If(self._command_issue.re, - self.phase.cs_n.eq(~self._cs.r), - self.phase.we_n.eq(~self._we.r), - self.phase.cas_n.eq(~self._cas.r), - self.phase.ras_n.eq(~self._ras.r) + phase.cs_n.eq(~self._cs.r), + phase.we_n.eq(~self._we.r), + phase.cas_n.eq(~self._cas.r), + phase.ras_n.eq(~self._ras.r) ).Else( - self.phase.cs_n.eq(1), - self.phase.we_n.eq(1), - self.phase.cas_n.eq(1), - self.phase.ras_n.eq(1) + phase.cs_n.eq(1), + phase.we_n.eq(1), + phase.cas_n.eq(1), + phase.ras_n.eq(1) ), - self.phase.address.eq(self._address.field.r), - self.phase.bank.eq(self._baddress.field.r), - self.phase.wrdata_en.eq(self._command_issue.re & self._wren.r), - self.phase.rddata_en.eq(self._command_issue.re & self._rden.r), - self.phase.wrdata.eq(self._wrdata.field.r), - self.phase.wrdata_mask.eq(0) - ] - sync = [ - If(self.phase.rddata_valid, self._rddata.field.w.eq(self.phase.rddata)) + phase.address.eq(self._address.field.r), + phase.bank.eq(self._baddress.field.r), + phase.wrdata_en.eq(self._command_issue.re & self._wren.r), + phase.rddata_en.eq(self._command_issue.re & self._rden.r), + phase.wrdata.eq(self._wrdata.field.r), + phase.wrdata_mask.eq(0) ] - return Fragment(comb, sync) + self.sync += If(phase.rddata_valid, self._rddata.field.w.eq(phase.rddata)) -class DFIInjector: - def __init__(self, csr_address, a, ba, d, nphases=1): - self._int = dfi.Interface(a, ba, d, nphases) +class DFIInjector(Module, AutoReg): + def __init__(self, a, ba, d, nphases=1): + inti = dfi.Interface(a, ba, d, nphases) self.slave = dfi.Interface(a, ba, d, nphases) self.master = dfi.Interface(a, ba, d, nphases) @@ -63,19 +54,12 @@ class DFIInjector: self._cke = Field("cke") self._control = RegisterFields("control", [self._sel, self._cke]) - self._phase_injectors = [PhaseInjector(phase) for phase in self._int.phases] - - registers = sum([pi.get_registers() for pi in self._phase_injectors], [self._control]) - self.bank = csrgen.Bank(registers, address=csr_address) + for n, phase in enumerate(inti.phases): + setattr(self.submodules, "pi" + str(n), PhaseInjector(phase)) + + ### - def get_fragment(self): - connect_int = dfi.interconnect_stmts(self._int, self.master) + connect_inti = dfi.interconnect_stmts(inti, self.master) connect_slave = dfi.interconnect_stmts(self.slave, self.master) - comb = [ - If(self._sel.r, *connect_slave).Else(*connect_int) - ] - comb += [phase.cke.eq(self._cke.r) for phase in self._int.phases] - - return Fragment(comb) \ - + sum([pi.get_fragment() for pi in self._phase_injectors], Fragment()) \ - + self.bank.get_fragment() + self.comb += If(self._sel.r, *connect_slave).Else(*connect_inti) + self.comb += [phase.cke.eq(self._cke.r) for phase in inti.phases] diff --git a/milkymist/framebuffer/__init__.py b/milkymist/framebuffer/__init__.py index 4106ce8c..f0b6b1c3 100644 --- a/milkymist/framebuffer/__init__.py +++ b/milkymist/framebuffer/__init__.py @@ -1,12 +1,12 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Instance +from migen.fhdl.module import Module from migen.flow.actor import * from migen.flow.network import * from migen.flow.transactions import * from migen.flow import plumbing from migen.actorlib import misc, dma_asmi, structuring, sim, spi from migen.bank.description import * -from migen.bank import csrgen _hbits = 11 _vbits = 11 @@ -47,7 +47,7 @@ class _FrameInitiator(spi.SingleGenerator): ] spi.SingleGenerator.__init__(self, layout, spi.MODE_CONTINUOUS) -class VTG(Actor): +class VTG(Module, Actor): def __init__(self): Actor.__init__(self, ("timing", Sink, [ @@ -62,8 +62,7 @@ class VTG(Actor): ("pixels", Sink, _pixel_layout), ("dac", Source, _dac_layout) ) - - def get_fragment(self): + hactive = Signal() vactive = Signal() active = Signal() @@ -73,7 +72,7 @@ class VTG(Actor): vcounter = Signal(_vbits) skip = _bpc - _bpc_dac - comb = [ + self.comb += [ active.eq(hactive & vactive), If(active, self.token("dac").r.eq(self.token("pixels").r[skip:]), @@ -86,7 +85,7 @@ class VTG(Actor): self.endpoints["dac"].stb.eq(generate_en) ] tp = self.token("timing") - sync = [ + self.sync += [ self.endpoints["timing"].ack.eq(0), If(generate_en & self.endpoints["dac"].ack, hcounter.eq(hcounter + 1), @@ -111,10 +110,8 @@ class VTG(Actor): If(vcounter == tp.vsync_end, self.token("dac").vsync.eq(0)) ) ] - - return Fragment(comb, sync) -class FIFO(Actor): +class FIFO(Module, Actor): def __init__(self): Actor.__init__(self, ("dac", Sink, _dac_layout)) @@ -124,13 +121,14 @@ class FIFO(Actor): self.vga_g = Signal(_bpc_dac) self.vga_b = Signal(_bpc_dac) - def get_fragment(self): + ### + data_width = 2+3*_bpc_dac fifo_full = Signal() fifo_write_en = Signal() fifo_data_out = Signal(data_width) fifo_data_in = Signal(data_width) - asfifo = Instance("asfifo", + self.specials += Instance("asfifo", Instance.Parameter("data_width", data_width), Instance.Parameter("address_width", 8), @@ -146,17 +144,15 @@ class FIFO(Actor): Instance.Input("rst", 0)) t = self.token("dac") - return Fragment( - [ - Cat(self.vga_hsync_n, self.vga_vsync_n, self.vga_r, self.vga_g, self.vga_b).eq(asfifo.get_io("data_out")), - - self.endpoints["dac"].ack.eq(~fifo_full), - fifo_write_en.eq(self.endpoints["dac"].stb), - fifo_data_in.eq(Cat(~t.hsync, ~t.vsync, t.r, t.g, t.b)), - - self.busy.eq(0) - ], - specials={asfifo}) + self.comb += [ + Cat(self.vga_hsync_n, self.vga_vsync_n, self.vga_r, self.vga_g, self.vga_b).eq(fifo_data_out), + + self.endpoints["dac"].ack.eq(~fifo_full), + fifo_write_en.eq(self.endpoints["dac"].stb), + fifo_data_in.eq(Cat(~t.hsync, ~t.vsync, t.r, t.g, t.b)), + + self.busy.eq(0) + ] def sim_fifo_gen(): while True: @@ -165,9 +161,8 @@ def sim_fifo_gen(): print("H/V:" + str(t.value["hsync"]) + str(t.value["vsync"]) + " " + str(t.value["r"]) + " " + str(t.value["g"]) + " " + str(t.value["b"])) - -class Framebuffer: - def __init__(self, address, asmiport, simulation=False): +class Framebuffer(Module): + def __init__(self, asmiport, simulation=False): asmi_bits = asmiport.hub.aw alignment_bits = bits_for(asmiport.hub.dw//8) - 1 length_bits = _hbits + _vbits + 2 - alignment_bits @@ -199,10 +194,9 @@ class Framebuffer: "hres", "hsync_start", "hsync_end", "hscan", "vres", "vsync_start", "vsync_end", "vscan"]) g.add_connection(vtg, fifo) - self._comp_actor = CompositeActor(g, debugger=False) + self.submodules._comp_actor = CompositeActor(g, debugger=False) - self.bank = csrgen.Bank(fi.get_registers() + self._comp_actor.get_registers(), - address=address) + self._registers = fi.get_registers() + self._comp_actor.get_registers() # Pads self.vga_psave_n = Signal() @@ -216,12 +210,11 @@ class Framebuffer: self.vga_g = fifo.vga_g self.vga_b = fifo.vga_b - def get_fragment(self): - comb = [ + self.comb += [ self.vga_sync_n.eq(0), self.vga_psave_n.eq(1), self.vga_blank_n.eq(1) ] - return self.bank.get_fragment() \ - + self._comp_actor.get_fragment() \ - + Fragment(comb) + + def get_registers(self): + return self._registers diff --git a/milkymist/identifier/__init__.py b/milkymist/identifier/__init__.py index 9ddeda78..8d56f27c 100644 --- a/milkymist/identifier/__init__.py +++ b/milkymist/identifier/__init__.py @@ -1,8 +1,8 @@ +import re + from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bank.description import * -from migen.bank import csrgen - -import re def encode_version(version): match = re.match("(\d+)\.(\d+)(\.(\d+))?(rc(\d+))?", version, re.IGNORECASE) @@ -15,22 +15,16 @@ def encode_version(version): r |= int(rc) return r -class Identifier: - def __init__(self, address, sysid, version, frequency): - self.sysid = sysid - self.version = encode_version(version) - self.frequency = frequency - +class Identifier(Module, AutoReg): + def __init__(self, sysid, version, frequency): self._r_sysid = RegisterField("sysid", 16, access_bus=READ_ONLY, access_dev=WRITE_ONLY) self._r_version = RegisterField("version", 16, access_bus=READ_ONLY, access_dev=WRITE_ONLY) self._r_frequency = RegisterField("frequency", 32, access_bus=READ_ONLY, access_dev=WRITE_ONLY) - regs = [self._r_sysid, self._r_version, self._r_frequency] - self.bank = csrgen.Bank(regs, address=address) - def get_fragment(self): - comb = [ - self._r_sysid.field.w.eq(self.sysid), - self._r_version.field.w.eq(self.version), - self._r_frequency.field.w.eq(self.frequency) + ### + + self.comb += [ + self._r_sysid.field.w.eq(sysid), + self._r_version.field.w.eq(encode_version(version)), + self._r_frequency.field.w.eq(frequency) ] - return self.bank.get_fragment() + Fragment(comb) diff --git a/milkymist/lm32/__init__.py b/milkymist/lm32/__init__.py index e2c743f9..6f398498 100644 --- a/milkymist/lm32/__init__.py +++ b/milkymist/lm32/__init__.py @@ -1,23 +1,27 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Instance +from migen.fhdl.module import Module from migen.bus import wishbone -class LM32: +class LM32(Module): def __init__(self): self.ibus = i = wishbone.Interface() self.dbus = d = wishbone.Interface() self.interrupt = Signal(32) self.ext_break = Signal() - self._i_adr_o = Signal(32) - self._d_adr_o = Signal(32) - self._inst = Instance("lm32_top", + + ### + + i_adr_o = Signal(32) + d_adr_o = Signal(32) + self.specials += Instance("lm32_top", Instance.ClockPort("clk_i"), Instance.ResetPort("rst_i"), Instance.Input("interrupt", self.interrupt), #Instance.Input("ext_break", self.ext_break), - Instance.Output("I_ADR_O", self._i_adr_o), + Instance.Output("I_ADR_O", i_adr_o), Instance.Output("I_DAT_O", i.dat_w), Instance.Output("I_SEL_O", i.sel), Instance.Output("I_CYC_O", i.cyc), @@ -31,7 +35,7 @@ class LM32: Instance.Input("I_ERR_I", i.err), Instance.Input("I_RTY_I", 0), - Instance.Output("D_ADR_O", self._d_adr_o), + Instance.Output("D_ADR_O", d_adr_o), Instance.Output("D_DAT_O", d.dat_w), Instance.Output("D_SEL_O", d.sel), Instance.Output("D_CYC_O", d.cyc), @@ -45,9 +49,7 @@ class LM32: Instance.Input("D_ERR_I", d.err), Instance.Input("D_RTY_I", 0)) - def get_fragment(self): - comb = [ - self.ibus.adr.eq(self._i_adr_o[2:]), - self.dbus.adr.eq(self._d_adr_o[2:]) + self.comb += [ + self.ibus.adr.eq(i_adr_o[2:]), + self.dbus.adr.eq(d_adr_o[2:]) ] - return Fragment(comb, specials={self._inst}) diff --git a/milkymist/m1crg/__init__.py b/milkymist/m1crg/__init__.py index baef9497..8218a506 100644 --- a/milkymist/m1crg/__init__.py +++ b/milkymist/m1crg/__init__.py @@ -2,9 +2,10 @@ from fractions import Fraction from migen.fhdl.structure import * from migen.fhdl.specials import Instance +from migen.fhdl.module import Module from mibuild.crg import CRG -class M1CRG(CRG): +class M1CRG(Module, CRG): def __init__(self, infreq, outfreq1x): self.clk50_pad = Signal() self.trigger_reset = Signal() @@ -56,7 +57,4 @@ class M1CRG(CRG): setattr(self, name, s) inst_items.append(Instance.Output(name, s)) - self._inst = Instance("m1crg", *inst_items) - - def get_fragment(self): - return Fragment(specials={self._inst}) + self.specials += Instance("m1crg", *inst_items) diff --git a/milkymist/minimac3/__init__.py b/milkymist/minimac3/__init__.py index 8c8d68d4..cdbdf45e 100644 --- a/milkymist/minimac3/__init__.py +++ b/milkymist/minimac3/__init__.py @@ -1,14 +1,14 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Instance +from migen.fhdl.module import Module from migen.bank.description import * from migen.bank.eventmanager import * -from migen.bank import csrgen from migen.bus import wishbone _count_width = 11 -class MiniMAC: - def __init__(self, address): +class MiniMAC(Module, AutoReg): + def __init__(self): # PHY signals self.phy_tx_clk = Signal() self.phy_tx_data = Signal(4) @@ -28,52 +28,52 @@ class MiniMAC: self._rx_count_1 = RegisterField("rx_count_1", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY) self._tx_count = RegisterField("tx_count", _count_width, access_dev=READ_WRITE) self._tx_start = RegisterRaw("tx_start") - regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count, self._tx_start] - self._rx_event_0 = EventSourcePulse() - self._rx_event_1 = EventSourcePulse() - self._tx_event = EventSourcePulse() - self.events = EventManager(self._rx_event_0, self._rx_event_1, self._tx_event) + self.submodules.ev = EventManager() + self.ev.rx0 = EventSourcePulse() + self.ev.rx1 = EventSourcePulse() + self.ev.tx = EventSourcePulse() + self.ev.finalize() - self.bank = csrgen.Bank(regs + self.events.get_registers(), address=address) self.membus = wishbone.Interface() - def get_fragment(self): + ### + init = Signal(reset=1) + self.sync += init.eq(0) rx_ready_0 = Signal() rx_ready_1 = Signal() - rx_pending_0 = self._rx_event_0.pending - rx_pending_1 = self._rx_event_1.pending + rx_pending_0 = self.ev.rx0.pending + rx_pending_1 = self.ev.rx1.pending rx_pending_0_r = Signal() rx_pending_1_r = Signal() - comb = [ + self.comb += [ self.phy_rst_n.eq(~self._phy_reset.field.r), rx_ready_0.eq(init | (rx_pending_0_r & ~rx_pending_0)), rx_ready_1.eq(init | (rx_pending_1_r & ~rx_pending_1)), self._tx_count.field.w.eq(0), - self._tx_count.field.we.eq(self._tx_event.trigger) + self._tx_count.field.we.eq(self.ev.tx.trigger) ] - sync = [ - init.eq(0), + self.sync += [ rx_pending_0_r.eq(rx_pending_0), rx_pending_1_r.eq(rx_pending_1) ] - inst = Instance("minimac3", + self.specials += Instance("minimac3", Instance.ClockPort("sys_clk"), Instance.ResetPort("sys_rst"), - Instance.Output("rx_done_0", self._rx_event_0.trigger), + Instance.Output("rx_done_0", self.ev.rx0.trigger), Instance.Output("rx_count_0", self._rx_count_0.field.w), - Instance.Output("rx_done_1", self._rx_event_1.trigger), + Instance.Output("rx_done_1", self.ev.rx1.trigger), Instance.Output("rx_count_1", self._rx_count_1.field.w), Instance.Input("rx_ready_0", rx_ready_0), Instance.Input("rx_ready_1", rx_ready_1), Instance.Input("tx_start", self._tx_start.re), Instance.Input("tx_count", self._tx_count.field.r), - Instance.Output("tx_done", self._tx_event.trigger), + Instance.Output("tx_done", self.ev.tx.trigger), Instance.Input("wb_adr_i", self.membus.adr), Instance.Input("wb_dat_i", self.membus.dat_w), @@ -94,6 +94,3 @@ class MiniMAC: Instance.Input("phy_rx_er", self.phy_rx_er), Instance.Input("phy_col", self.phy_col), Instance.Input("phy_crs", self.phy_crs)) - return Fragment(comb, sync, specials={inst}) \ - + self.events.get_fragment() \ - + self.bank.get_fragment() diff --git a/milkymist/norflash/__init__.py b/milkymist/norflash/__init__.py index e8e97f31..f88d8818 100644 --- a/milkymist/norflash/__init__.py +++ b/milkymist/norflash/__init__.py @@ -1,12 +1,10 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bus import wishbone from migen.genlib.misc import timeline -class NorFlash: +class NorFlash(Module): def __init__(self, adr_width, rd_timing): - self.adr_width = adr_width - self.rd_timing = rd_timing - self.bus = wishbone.Interface() self.adr = Signal(adr_width-1) self.d = Signal(16) @@ -14,18 +12,18 @@ class NorFlash: self.we_n = Signal() self.ce_n = Signal() - def get_fragment(self): - comb = [self.oe_n.eq(0), self.we_n.eq(1), + ### + + self.comb += [self.oe_n.eq(0), self.we_n.eq(1), self.ce_n.eq(0)] - sync = timeline(self.bus.cyc & self.bus.stb, [ - (0, [self.adr.eq(Cat(0, self.bus.adr[:self.adr_width-2]))]), - (self.rd_timing, [ + self.sync += timeline(self.bus.cyc & self.bus.stb, [ + (0, [self.adr.eq(Cat(0, self.bus.adr[:adr_width-2]))]), + (rd_timing, [ self.bus.dat_r[16:].eq(self.d), - self.adr.eq(Cat(1, self.bus.adr[:self.adr_width-2]))]), - (2*self.rd_timing, [ + self.adr.eq(Cat(1, self.bus.adr[:adr_width-2]))]), + (2*rd_timing, [ self.bus.dat_r[:16].eq(self.d), self.bus.ack.eq(1)]), - (2*self.rd_timing + 1, [ + (2*rd_timing + 1, [ self.bus.ack.eq(0)]) ]) - return Fragment(comb, sync) diff --git a/milkymist/s6ddrphy/__init__.py b/milkymist/s6ddrphy/__init__.py index 3f16baf1..873f7d33 100644 --- a/milkymist/s6ddrphy/__init__.py +++ b/milkymist/s6ddrphy/__init__.py @@ -1,8 +1,9 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Instance +from migen.fhdl.module import Module from migen.bus import dfi -class S6DDRPHY: +class S6DDRPHY(Module): def __init__(self, a, ba, d): inst_items = [ Instance.Parameter("NUM_AD", a), @@ -39,7 +40,4 @@ class S6DDRPHY: inst_items += [Instance.Output(name, signal) for name, signal in self.dfi.get_standard_names(False, True)] - self._inst = Instance("s6ddrphy", *inst_items) - - def get_fragment(self): - return Fragment(specials={self._inst}) + self.specials += Instance("s6ddrphy", *inst_items) diff --git a/milkymist/timer/__init__.py b/milkymist/timer/__init__.py index 85b5cb53..be51d33a 100644 --- a/milkymist/timer/__init__.py +++ b/milkymist/timer/__init__.py @@ -1,30 +1,26 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module from migen.bank.description import * from migen.bank.eventmanager import * -from migen.bank import csrgen -class Timer: - def __init__(self, address, width=32): +class Timer(Module, AutoReg): + def __init__(self, width=32): self._en = RegisterField("en") self._value = RegisterField("value", width, access_dev=READ_WRITE) self._reload = RegisterField("reload", width) - regs = [self._en, self._value, self._reload] - self.event = EventSourceLevel() - self.events = EventManager(self.event) - - self.bank = csrgen.Bank(regs + self.events.get_registers(), address=address) + self.submodules.ev = EventManager() + self.ev.zero = EventSourceLevel() + self.ev.finalize() + + ### - def get_fragment(self): - comb = [ + self.comb += [ If(self._value.field.r == 0, self._value.field.w.eq(self._reload.field.r) ).Else( self._value.field.w.eq(self._value.field.r - 1) ), self._value.field.we.eq(self._en.field.r), - self.event.trigger.eq(self._value.field.r != 0) + self.ev.zero.trigger.eq(self._value.field.r != 0) ] - return Fragment(comb) \ - + self.events.get_fragment() \ - + self.bank.get_fragment() diff --git a/milkymist/uart/__init__.py b/milkymist/uart/__init__.py index 597885ff..d1eca795 100644 --- a/milkymist/uart/__init__.py +++ b/milkymist/uart/__init__.py @@ -1,29 +1,28 @@ from migen.fhdl.structure import * +from migen.fhdl.module import Module +from migen.genlib.cdc import MultiReg from migen.bank.description import * from migen.bank.eventmanager import * -from migen.bank import csrgen -class UART: - def __init__(self, address, clk_freq, baud=115200): +class UART(Module, AutoReg): + def __init__(self, clk_freq, baud=115200): self._rxtx = RegisterRaw("rxtx", 8) self._divisor = RegisterField("divisor", 16, reset=int(clk_freq/baud/16)) - self._tx_event = EventSourceLevel() - self._rx_event = EventSourcePulse() - self.events = EventManager(self._tx_event, self._rx_event) - self.bank = csrgen.Bank([self._rxtx, self._divisor] + self.events.get_registers(), - address=address) + self.submodules.ev = EventManager() + self.ev.tx = EventSourceLevel() + self.ev.rx = EventSourcePulse() + self.ev.finalize() self.tx = Signal(reset=1) self.rx = Signal() - def get_fragment(self): + ### + enable16 = Signal() enable16_counter = Signal(16) - comb = [ - enable16.eq(enable16_counter == 0) - ] - sync = [ + self.comb += enable16.eq(enable16_counter == 0) + self.sync += [ enable16_counter.eq(enable16_counter - 1), If(enable16, enable16_counter.eq(self._divisor.field.r - 1)) @@ -33,8 +32,8 @@ class UART: tx_reg = Signal(8) tx_bitcount = Signal(4) tx_count16 = Signal(4) - tx_busy = self._tx_event.trigger - sync += [ + tx_busy = self.ev.tx.trigger + self.sync += [ If(self._rxtx.re, tx_reg.eq(self._rxtx.r), tx_bitcount.eq(0), @@ -59,20 +58,16 @@ class UART: ] # RX - rx0 = Signal() # sychronize rx = Signal() - sync += [ - rx0.eq(self.rx), - rx.eq(rx0) - ] + self.specials += MultiReg(self.rx, "ext", rx, "sys") rx_r = Signal() rx_reg = Signal(8) rx_bitcount = Signal(4) rx_count16 = Signal(4) rx_busy = Signal() - rx_done = self._rx_event.trigger + rx_done = self.ev.rx.trigger rx_data = self._rxtx.w - sync += [ + self.sync += [ rx_done.eq(0), If(enable16, rx_r.eq(rx), @@ -104,7 +99,3 @@ class UART: ) ) ] - - return self.bank.get_fragment() \ - + self.events.get_fragment() \ - + Fragment(comb, sync) diff --git a/software/include/hw/id.h b/software/include/hw/id.h deleted file mode 100644 index 574dbb62..00000000 --- a/software/include/hw/id.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __HW_ID_H -#define __HW_ID_H - -#include -#include - -#define ID_CSR(x) MMPTR(ID_BASE+(x)) - -#define CSR_ID_SYSTEMH ID_CSR(0x00) -#define CSR_ID_SYSTEML ID_CSR(0x04) -#define CSR_ID_VERSIONH ID_CSR(0x08) -#define CSR_ID_VERSIONL ID_CSR(0x0C) -#define CSR_ID_FREQ3 ID_CSR(0x10) -#define CSR_ID_FREQ2 ID_CSR(0x14) -#define CSR_ID_FREQ1 ID_CSR(0x18) -#define CSR_ID_FREQ0 ID_CSR(0x1C) - -#endif /* __HW_ID_H */ diff --git a/software/include/hw/identifier.h b/software/include/hw/identifier.h new file mode 100644 index 00000000..3c13ca9f --- /dev/null +++ b/software/include/hw/identifier.h @@ -0,0 +1,18 @@ +#ifndef __HW_IDENTIFIER_H +#define __HW_IDENTIFIER_H + +#include +#include + +#define IDENTIFIER_CSR(x) MMPTR(IDENTIFIER_BASE+(x)) + +#define CSR_IDENTIFIER_SYSTEMH IDENTIFIER_CSR(0x00) +#define CSR_IDENTIFIER_SYSTEML IDENTIFIER_CSR(0x04) +#define CSR_IDENTIFIER_VERSIONH IDENTIFIER_CSR(0x08) +#define CSR_IDENTIFIER_VERSIONL IDENTIFIER_CSR(0x0C) +#define CSR_IDENTIFIER_FREQ3 IDENTIFIER_CSR(0x10) +#define CSR_IDENTIFIER_FREQ2 IDENTIFIER_CSR(0x14) +#define CSR_IDENTIFIER_FREQ1 IDENTIFIER_CSR(0x18) +#define CSR_IDENTIFIER_FREQ0 IDENTIFIER_CSR(0x1C) + +#endif /* __HW_IDENTIFIER_H */ diff --git a/software/libbase/board.c b/software/libbase/board.c index b58900a2..97b18a3b 100644 --- a/software/libbase/board.c +++ b/software/libbase/board.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -27,7 +27,7 @@ static const struct board_desc *get_board_desc_id(unsigned short int id) static const struct board_desc *get_board_desc(void) { - return get_board_desc_id((CSR_ID_SYSTEMH << 8) | CSR_ID_SYSTEML); + return get_board_desc_id((CSR_IDENTIFIER_SYSTEMH << 8) | CSR_IDENTIFIER_SYSTEML); } int get_pcb_revision(void) @@ -54,10 +54,10 @@ void get_soc_version(unsigned int *major, unsigned int *minor, unsigned int *sub { unsigned int id; - id = CSR_ID_VERSIONH; + id = CSR_IDENTIFIER_VERSIONH; *major = (id & 0xf0) >> 4; *minor = id & 0x0f; - id = CSR_ID_VERSIONL; + id = CSR_IDENTIFIER_VERSIONL; *subminor = (id & 0xf0) >> 4; *rc = id & 0x0f; } diff --git a/software/libbase/timer.c b/software/libbase/timer.c index c2c4b9da..ea25eb5e 100644 --- a/software/libbase/timer.c +++ b/software/libbase/timer.c @@ -1,14 +1,14 @@ #include -#include +#include #include "timer.h" unsigned int get_system_frequency(void) { - return (CSR_ID_FREQ3 << 24) - |(CSR_ID_FREQ2 << 16) - |(CSR_ID_FREQ1 << 8) - |CSR_ID_FREQ0; + return (CSR_IDENTIFIER_FREQ3 << 24) + |(CSR_IDENTIFIER_FREQ2 << 16) + |(CSR_IDENTIFIER_FREQ1 << 8) + |CSR_IDENTIFIER_FREQ0; } void timer_enable(int en) diff --git a/top.py b/top.py index 70e1e78b..715183ac 100644 --- a/top.py +++ b/top.py @@ -2,8 +2,9 @@ from fractions import Fraction from math import ceil from migen.fhdl.structure import * -from migen.fhdl import verilog, autofragment +from migen.fhdl.module import Module from migen.bus import wishbone, wishbone2asmi, csr, wishbone2csr, dfi +from migen.bank import csrgen from milkymist import m1crg, lm32, norflash, uart, s6ddrphy, dfii, asmicon, \ identifier, timer, minimac3, framebuffer, asmiprobe @@ -57,12 +58,17 @@ def interrupt_n(name): version = get_macros("common/version.h")["VERSION"][1:-1] -class SoC: +def csr_address_map(name, memory): + if memory is not None: + name += "_" + memory.name_override + return csr_offset(name.upper()) + +class SoC(Module): def __init__(self): # # ASMI # - self.asmicon = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing) + self.submodules.asmicon = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing) asmiport_wb = self.asmicon.hub.get_port() asmiport_fb = self.asmicon.hub.get_port(2) self.asmicon.finalize() @@ -70,21 +76,21 @@ class SoC: # # DFI # - self.ddrphy = s6ddrphy.S6DDRPHY(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d) - self.dfii = dfii.DFIInjector(csr_offset("DFII"), - sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d, sdram_phy.nphases) - self.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi) - self.dficon1 = dfi.Interconnect(self.asmicon.dfi, self.dfii.slave) + self.submodules.ddrphy = s6ddrphy.S6DDRPHY(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d) + self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d, + sdram_phy.nphases) + self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi) + self.submodules.dficon1 = dfi.Interconnect(self.asmicon.dfi, self.dfii.slave) # # WISHBONE # - self.cpu = lm32.LM32() - self.norflash = norflash.NorFlash(25, 12) - self.sram = wishbone.SRAM(sram_size) - self.minimac = minimac3.MiniMAC(csr_offset("MINIMAC")) - self.wishbone2asmi = wishbone2asmi.WB2ASMI(l2_size//4, asmiport_wb) - self.wishbone2csr = wishbone2csr.WB2CSR() + self.submodules.cpu = lm32.LM32() + self.submodules.norflash = norflash.NorFlash(25, 12) + self.submodules.sram = wishbone.SRAM(sram_size) + self.submodules.minimac = minimac3.MiniMAC() + self.submodules.wishbone2asmi = wishbone2asmi.WB2ASMI(l2_size//4, asmiport_wb) + self.submodules.wishbone2csr = wishbone2csr.WB2CSR() # norflash 0x00000000 (shadow @0x80000000) # SRAM/debug 0x10000000 (shadow @0x90000000) @@ -92,7 +98,7 @@ class SoC: # Ethernet 0x30000000 (shadow @0xb0000000) # SDRAM 0x40000000 (shadow @0xc0000000) # CSR bridge 0x60000000 (shadow @0xe0000000) - self.wishbonecon = wishbone.InterconnectShared( + self.submodules.wishbonecon = wishbone.InterconnectShared( [ self.cpu.ibus, self.cpu.dbus @@ -108,39 +114,29 @@ class SoC: # # CSR # - self.uart = uart.UART(csr_offset("UART"), clk_freq, baud=115200) - self.identifier = identifier.Identifier(csr_offset("ID"), 0x4D31, version, int(clk_freq)) - self.timer = timer.Timer(csr_offset("TIMER0")) - self.fb = framebuffer.Framebuffer(csr_offset("FB"), asmiport_fb) - self.asmiprobe = asmiprobe.ASMIprobe(csr_offset("ASMIPROBE"), self.asmicon.hub) - self.csrcon = csr.Interconnect(self.wishbone2csr.csr, [ - self.uart.bank.bus, - self.dfii.bank.bus, - self.identifier.bank.bus, - self.timer.bank.bus, - self.minimac.bank.bus, - self.fb.bank.bus, - self.asmiprobe.bank.bus - ]) + self.submodules.uart = uart.UART(clk_freq, baud=115200) + self.submodules.identifier = identifier.Identifier(0x4D31, version, int(clk_freq)) + self.submodules.timer0 = timer.Timer() + self.submodules.fb = framebuffer.Framebuffer(asmiport_fb) + self.submodules.asmiprobe = asmiprobe.ASMIprobe(self.asmicon.hub) + + self.submodules.csrbankarray = csrgen.BankArray(self, csr_address_map) + self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses()) + + # + # Interrupts + # + self.comb += [ + self.cpu.interrupt[interrupt_n("UART")].eq(self.uart.ev.irq), + self.cpu.interrupt[interrupt_n("TIMER0")].eq(self.timer0.ev.irq), + self.cpu.interrupt[interrupt_n("MINIMAC")].eq(self.minimac.ev.irq) + ] # # Clocking # - self.crg = m1crg.M1CRG(50*MHz, clk_freq) - - def get_fragment(self): - comb = [ - # - # Interrupts - # - self.cpu.interrupt[interrupt_n("UART")].eq(self.uart.events.irq), - self.cpu.interrupt[interrupt_n("TIMER0")].eq(self.timer.events.irq), - self.cpu.interrupt[interrupt_n("MINIMAC")].eq(self.minimac.events.irq), - # - # DDR PHY strobes - # + self.submodules.crg = m1crg.M1CRG(50*MHz, clk_freq) + self.comb += [ self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb), self.ddrphy.clk4x_rd_strb.eq(self.crg.clk4x_rd_strb) ] - glue = Fragment(comb) - return glue + autofragment.from_attributes(self)