def _impl(self): self._parseTemplate() # build read data output mux st_t = HEnum('st_t', ['idle', 'readDelay', 'rdData']) bus = self.bus addr = bus.address addrVld = bus.read | bus.write st = FsmBuilder(self, st_t)\ .Trans(st_t.idle, (addrVld & bus.read, st_t.rdData), (addrVld & bus.write, st_t.idle) ).Trans(st_t.readDelay, st_t.rdData ).Trans(st_t.rdData, st_t.idle ).stateReg wAck = True wr = bus.write & wAck isInAddrRange = (self.isInMyAddrRange(bus.address)) If(isInAddrRange, bus.response(RESP_OKAY) ).Else( bus.response(RESP_SLAVEERROR) ) bus.waitRequest(bus.read & ~st._eq(st_t.rdData)) bus.readDataValid(st._eq(st_t.rdData)) bus.writeResponseValid(wr) ADDR_STEP = self._getAddrStep() dataToBus = bus.readData(None) for (_, _), t in reversed(self._bramPortMapped): # map addr for bram ports _addr = t.bitAddr // ADDR_STEP _isMyAddr = inRange(addr, _addr, t.bitAddrEnd // ADDR_STEP) wasMyAddr = self._reg("wasMyAddr") If(st._eq(st_t.idle), wasMyAddr(_isMyAddr) ) port = self.getPort(t) self.propagateAddr(addr, ADDR_STEP, port.addr, port.dout._dtype.bit_length(), t) port.en(_isMyAddr & addrVld) port.we(_isMyAddr & wr) dataToBus = If(wasMyAddr & st._eq(st_t.rdData), bus.readData(port.dout) ).Else( dataToBus ) port.din(bus.writeData) self.connect_directly_mapped_write(addr, bus.writeData, wr) self.connect_directly_mapped_read(bus.address, bus.readData, dataToBus)
def translate_addr_signal(self, mem_map, sig_in, sig_out): cases = [] AW = sig_in._dtype.bit_length() for (offset_in, size, offset_out) in mem_map: in_is_aligned = offset_in % size == 0 and isPow2(size) out_is_aligned = offset_out % size == 0 and isPow2(size) if in_is_aligned: L = (size - 1).bit_length() en_sig = sig_in[:L]._eq(offset_in >> L) _sig_in = sig_in[L:] if out_is_aligned: addr_drive = Concat( Bits(AW - L).from_py(offset_out), _sig_in) else: addr_drive = Concat(Bits(AW - L).from_py(0), _sig_in) + offset_out else: en_sig = inRange(sig_in, offset_in, offset_in + size) if offset_in == offset_out: addr_drive = sig_in elif offset_in < offset_out: addr_drive = sig_in + (offset_out - offset_in) else: # offset_in > offset_out: addr_drive = sig_in - (offset_in - offset_out) cases.append((en_sig, sig_out(addr_drive))) SwitchLogic(cases, default=sig_out(sig_in))
def _impl(self): self._parseTemplate() # build read data output mux st_t = HEnum('st_t', ['idle', "writeAck", 'readDelay', 'rdData']) ipif = self.bus addr = ipif.bus2ip_addr ipif.ip2bus_error(0) addrVld = ipif.bus2ip_cs isInMyAddrSpace = self.isInMyAddrRange(addr) st = FsmBuilder(self, st_t)\ .Trans(st_t.idle, (addrVld & isInMyAddrSpace & ipif.bus2ip_rnw, st_t.rdData), (addrVld & isInMyAddrSpace & ~ipif.bus2ip_rnw, st_t.writeAck) ).Trans(st_t.writeAck, st_t.idle ).Trans(st_t.readDelay, st_t.rdData ).Trans(st_t.rdData, st_t.idle ).stateReg wAck = st._eq(st_t.writeAck) ipif.ip2bus_rdack(st._eq(st_t.rdData)) ipif.ip2bus_wrack(wAck) ADDR_STEP = self._getAddrStep() dataToBus = ipif.ip2bus_data(None) for (_, _), t in reversed(self._bramPortMapped): # map addr for bram ports _addr = t.bitAddr // ADDR_STEP _isMyAddr = inRange(addr, _addr, t.bitAddrEnd // ADDR_STEP) port = self.getPort(t) self.propagateAddr(addr, ADDR_STEP, port.addr, port.dout._dtype.bit_length(), t) port.en(_isMyAddr & ipif.bus2ip_cs) port.we(_isMyAddr & wAck) dataToBus = If(_isMyAddr, ipif.ip2bus_data(port.dout)).Else(dataToBus) port.din(ipif.bus2ip_data) self.connect_directly_mapped_write(ipif.bus2ip_addr, ipif.bus2ip_data, ~ipif.bus2ip_rnw & wAck) self.connect_directly_mapped_read(ipif.bus2ip_addr, ipif.ip2bus_data, dataToBus)
def propagateAddr(self, src_addr_sig: RtlSignal, src_addr_step: int, dst_addr_sig: RtlSignal, dst_addr_step: int, transTmpl: TransTmpl): """ :param src_addr_sig: input signal with address :param src_addr_step: how many bits is addressing one unit of src_addr_sig :param dst_addr_sig: output signal for address :param dst_addr_step: how many bits is addressing one unit of dst_addr_sig :param transTmpl: TransTmpl which has meta-informations about this address space transition """ IN_W = src_addr_sig._dtype.bit_length() # _prefix = transTmpl.getMyAddrPrefix(src_addr_step) assert dst_addr_step % src_addr_step == 0 if not isinstance(transTmpl.dtype, HArray): raise TypeError(transTmpl.dtype) assert transTmpl.bitAddr % dst_addr_step == 0, ( f"Has to be addressable by address with this step ({transTmpl})") addrIsAligned = transTmpl.bitAddr % transTmpl.bit_length() == 0 bitsForAlignment = AddressStepTranslation(src_addr_step, dst_addr_step).align_bits bitsOfSubAddr = ((transTmpl.bitAddrEnd - transTmpl.bitAddr - 1) // dst_addr_step).bit_length() if addrIsAligned: bitsOfAddr = bitsOfSubAddr + bitsForAlignment bitsOfPrefix = IN_W - bitsOfAddr prefix = (transTmpl.bitAddr // src_addr_step) >> bitsOfAddr if bitsOfPrefix == 0: addrIsInRange = True else: addrIsInRange = src_addr_sig[:(IN_W - bitsOfPrefix)]._eq(prefix) addr_tmp = src_addr_sig else: _addr = transTmpl.bitAddr // src_addr_step _addrEnd = transTmpl.bitAddrEnd // src_addr_step addrIsInRange = inRange(src_addr_sig, _addr, _addrEnd) addr_tmp = self._sig(dst_addr_sig._name + "_addr_tmp", Bits(self.ADDR_WIDTH)) addr_tmp(src_addr_sig - _addr) addr_h = bitsOfSubAddr + bitsForAlignment connectedAddr = dst_addr_sig(addr_tmp[addr_h:bitsForAlignment]) return (addrIsInRange, connectedAddr)
def isInMyAddrRange(self, addr_sig): return inRange(addr_sig, self._ADDR_MIN, self._ADDR_MAX)
def translate_addr_val(self, mem_map, addr: int): for (offset_in, size, offset_out) in mem_map: if inRange(addr, offset_in, offset_in + size): return addr - (offset_in - offset_out) return addr