def test_type(): data_width = 32 apb_16_32 = APBMaster(16, data_width)() assert isinstance(apb_16_32.PCLK, m.ClockType) assert apb_16_32.PCLK.isoutput() assert isinstance(apb_16_32.PRESETn, m.ResetType) assert apb_16_32.PRESETn.isoutput() assert isinstance(apb_16_32.PADDR, m.BitsType) assert apb_16_32.PADDR.isoutput() assert isinstance(apb_16_32.PPROT, m.BitType) assert apb_16_32.PPROT.isoutput() assert isinstance(apb_16_32.PSEL0, m.BitType) assert apb_16_32.PSEL0.isoutput() assert isinstance(apb_16_32.PENABLE, m.BitType) assert apb_16_32.PENABLE.isoutput() assert isinstance(apb_16_32.PWRITE, m.BitType) assert apb_16_32.PWRITE.isoutput() assert isinstance(apb_16_32.PWDATA, m.BitsType) assert apb_16_32.PWDATA.isoutput() assert isinstance(apb_16_32.PSTRB, m.BitsType) assert apb_16_32.PSTRB.isoutput() assert len(apb_16_32.PSTRB) == data_width / 8 assert isinstance(apb_16_32.PREADY, m.BitType) assert apb_16_32.PREADY.isinput() assert isinstance(apb_16_32.PRDATA, m.BitsType) assert apb_16_32.PRDATA.isinput() assert isinstance(apb_16_32.PSLVERR, m.BitType) assert apb_16_32.PSLVERR.isinput() apb_slave_16_32 = APBSlave(16, data_width, 0)() assert isinstance(apb_slave_16_32.PCLK, m.ClockType) assert apb_slave_16_32.PCLK.isinput() assert isinstance(apb_slave_16_32.PRESETn, m.ResetType) assert apb_slave_16_32.PRESETn.isinput() assert isinstance(apb_slave_16_32.PADDR, m.BitsType) assert apb_slave_16_32.PADDR.isinput() assert isinstance(apb_slave_16_32.PPROT, m.BitType) assert apb_slave_16_32.PPROT.isinput() assert isinstance(apb_slave_16_32.PSEL0, m.BitType) assert apb_slave_16_32.PSEL0.isinput() assert isinstance(apb_slave_16_32.PENABLE, m.BitType) assert apb_slave_16_32.PENABLE.isinput() assert isinstance(apb_slave_16_32.PWRITE, m.BitType) assert apb_slave_16_32.PWRITE.isinput() assert isinstance(apb_slave_16_32.PWDATA, m.BitsType) assert apb_slave_16_32.PWDATA.isinput() assert isinstance(apb_slave_16_32.PSTRB, m.BitsType) assert apb_slave_16_32.PSTRB.isinput() assert len(apb_slave_16_32.PSTRB) == data_width / 8 assert isinstance(apb_slave_16_32.PREADY, m.BitType) assert apb_slave_16_32.PREADY.isoutput() assert isinstance(apb_slave_16_32.PRDATA, m.BitsType) assert apb_slave_16_32.PRDATA.isoutput() assert isinstance(apb_slave_16_32.PSLVERR, m.BitType) assert apb_slave_16_32.PSLVERR.isoutput() assert APBSlave(16, 32, 0).flip() == APBMaster(16, 32)
class Top(m.Circuit): if mode == "pack": IO = ["apb", APBSlave(addr_width, data_width, 0)] else: IO = ["apb", APBSlave(addr_width, data_width, [0, 1])] @classmethod def definition(io): dmas = [DMA(name=f"dma{i}") for i in range(2)] if mode == "pack": regs = [ Register(name + str(i)) for i in range(2) for name in fields ] reg_file = DefineRegFile(regs, data_width=32)(name="reg_file") for i in range(2): for name in fields: m.wire(getattr(reg_file, name + str(i) + "_q"), getattr(dmas[i], name)) m.wire(io.apb, reg_file.apb) for i in range(2): for name in fields: m.wire(getattr(reg_file, name + str(i) + "_q"), getattr(reg_file, name + str(i) + "_d")) else: apb_outputs = {} for key, type_ in APBBase(addr_width, data_width).items(): if type_.isinput(): apb_outputs[key] = [] for i in range(2): regs = [Register(name) for name in fields] reg_file = DefineRegFile( regs, data_width=32, apb_slave_id=i)(name=f"reg_file{i}") for name in fields: m.wire(getattr(reg_file, name + "_q"), getattr(dmas[i], name)) for key, type_ in APBBase(addr_width, data_width).items(): if type_.isoutput(): m.wire(getattr(io.apb, key), getattr(reg_file.apb, key)) else: apb_outputs[key].append(getattr(reg_file.apb, key)) m.wire(getattr(io.apb, f"PSEL{i}"), getattr(reg_file.apb, f"PSEL{i}")) for name in fields: m.wire(getattr(reg_file, name + "_q"), getattr(reg_file, name + "_d")) for key, values in apb_outputs.items(): m.wire(getattr(io.apb, key), mantle.mux(values, io.apb.PSEL1))
def __init__(self, mode="pack"): """ Simple example that instances two stub DMA modules and is paramtrizable over distributed versus packed register file """ if mode not in ["pack", "distribute"]: raise ValueError(f"Unexpected mode {mode}") fields = ["csr", "src_addr", "dst_addr", "txfr_len"] data_width = 32 addr_width = math.ceil(math.log2(len(fields) * 2)) self.name = "Top_" + mode self.io = io = m.IO(apb=APBSlave(addr_width, data_width, 0)) dmas = [DMA(name=f"dma{i}") for i in range(2)] regs = tuple(Register(name + str(i)) for i in range(2) for name in fields) reg_file = RegisterFileGenerator(regs, data_width=32)(name="reg_file") for i in range(2): for name in fields: m.wire(getattr(reg_file, name + str(i) + "_q"), getattr(dmas[i], name)) m.wire(io.apb, reg_file.apb) for i in range(2): for name in fields: m.wire(getattr(reg_file, name + str(i) + "_q"), getattr(reg_file, name + str(i) + "_d"))
def make_reg_file_interface(reg_list: Tuple[Register], data_width: int, apb_slave_id: int): # magma provides various helper functions in m.bitutils, # here we use clog2 to derive the number of bits required # to store the address space described by number of Registers # in `reg_list` addr_width = m.bitutils.clog2(len(reg_list)) Data = m.Bits[data_width] io = m.IO(apb=APBSlave(addr_width, data_width, apb_slave_id)) for reg in reg_list: io += m.IO(**{f"{reg.name}_d": m.In(Data)}) if reg.has_ce: io += m.IO(**{f"{reg.name}_en": m.In(m.Enable)}) io += m.IO(**{f"{reg.name}_q": m.Out(Data)}) return io
class RegFile(m.Circuit): IO = ["apb", APBSlave(addr_width, data_width, apb_slave_id)] for reg in reg_list: IO += [f"{reg.name}_d", m.In(Data)] if reg.has_ce: IO += [f"{reg.name}_en", m.In(m.Enable)] IO += [f"{reg.name}_q", m.Out(Data)] @classmethod def definition(io): PSEL = getattr(io.apb, f"PSEL{apb_slave_id}") registers = [ mantle.Register(data_width, init=reg.init, has_ce=True, has_reset=True, name=reg.name) for reg in reg_list ] is_write = io.apb.PENABLE & io.apb.PWRITE & PSEL ready = None for i, reg in enumerate(registers): reg.I <= mantle.mux( [getattr(io, reg.name + "_d"), io.apb.PWDATA], is_write) getattr(io, reg.name + "_q") <= reg.O reg.CLK <= io.apb.PCLK reg.RESET <= ~m.bit(io.apb.PRESETn) ce = is_write & (io.apb.PADDR == i) if reg_list[i].has_ce: reg.CE <= ce | m.bit(getattr(io, reg.name + "_en")) else: reg.CE <= ce if ready is not None: ready |= ce else: ready = ce is_read = io.apb.PENABLE & ~io.apb.PWRITE & PSEL io.apb.PREADY <= ready | is_read io.apb.PRDATA <= mantle.mux([reg.O for reg in registers], io.apb.PADDR) io.apb.PSLVERR <= 0 # Unused CorebitTerm().I <= io.apb.PPROT Term(len(io.apb.PSTRB)).I <= io.apb.PSTRB
def __init__(self, mode="pack"): """ Simple example that instances two stub DMA modules and is paramtrizable over distributed versus packed register file """ if mode not in ["pack", "distribute"]: raise ValueError(f"Unexpected mode {mode}") fields = ["csr", "src_addr", "dst_addr", "txfr_len"] data_width = 32 if mode == "pack": addr_width = math.ceil(math.log2(len(fields) * 2)) else: addr_width = math.ceil(math.log2(len(fields))) self.name = "Top_" + mode if mode == "pack": self.io = io = m.IO(apb=APBSlave(addr_width, data_width, 0)) else: self.io = io = m.IO(apb=APBSlave(addr_width, data_width, [0, 1])) dmas = [DMA(name=f"dma{i}") for i in range(2)] if mode == "pack": regs = tuple( Register(name + str(i)) for i in range(2) for name in fields) reg_file = RegisterFileGenerator(regs, data_width=32)(name="reg_file") for i in range(2): for name in fields: m.wire(getattr(reg_file, name + str(i) + "_q"), getattr(dmas[i], name)) m.wire(io.apb, reg_file.apb) for i in range(2): for name in fields: m.wire(getattr(reg_file, name + str(i) + "_q"), getattr(reg_file, name + str(i) + "_d")) else: apb_outputs = {} for key, type_ in APBBase(addr_width, data_width).items(): if type_.is_input(): apb_outputs[key] = [] for i in range(2): regs = tuple(Register(name) for name in fields) reg_file = RegisterFileGenerator( regs, data_width=32, apb_slave_id=i)(name=f"reg_file{i}") for name in fields: m.wire(getattr(reg_file, name + "_q"), getattr(dmas[i], name)) for key, type_ in APBBase(addr_width, data_width).items(): if type_.is_output(): m.wire(getattr(io.apb, key), getattr(reg_file.apb, key)) else: apb_outputs[key].append(getattr(reg_file.apb, key)) m.wire(getattr(io.apb, f"PSEL{i}"), getattr(reg_file.apb, f"PSEL{i}")) for name in fields: m.wire(getattr(reg_file, name + "_q"), getattr(reg_file, name + "_d")) for key, values in apb_outputs.items(): m.wire(getattr(io.apb, key), mantle.mux(values, io.apb.PSEL1))