Source code for hwt.serializer.resourceAnalyzer.utils

from typing import Union

from hwt.hdl.operator import Operator
from hwt.hdl.statements.statement import HdlStatement
from hwt.serializer.resourceAnalyzer.resourceTypes import \
    ResourceFF, ResourceMUX, ResourceLatch, ResourceRAM
from hwt.synthesizer.rtlLevel.rtlSignal import RtlSignal
from hwt.synthesizer.unit import Unit


[docs]class ResourceContext(): """ Container of informations about resources used in architecture :ivar ~.unit: optional unit for which is this context build :ivar ~.seen: set of seen objects :ivar ~.resources: dictionary {type of resource: cnt} :ivar ~.discoveredRamSignals: set of signals which seems to be some kind of RAM/ROM memory """
[docs] def __init__(self, unit: Unit): self.unit = unit self.seen = set() self.resources = {} # {RtlSignal or Statement or Operator: HwResource or typle (HwResource, cnt)} self.resource_for_object = {} # {(mem, addr, syncFlag, r/w): cnt} self.memories = {}
[docs] def registerOperator(self, op: Operator): w = op.operands[0]._dtype.bit_length() res = self.resources k = (op.operator, w) res[k] = res.get(k, 0) + 1 self.resource_for_object[op] = k
[docs] def registerMUX(self, stm: Union[HdlStatement, Operator], sig: RtlSignal, inputs_cnt: int): """ mux record is in format (self.MUX, n, m) where n is number of bits of this mux and m is number of possible inputs """ assert inputs_cnt > 1 res = self.resources w = sig._dtype.bit_length() k = (ResourceMUX, w, inputs_cnt) res[k] = res.get(k, 0) + 1 self.resource_for_object[(stm, sig)] = k
[docs] def registerFF(self, ff): res = self.resources w = ff._dtype.bit_length() ffs = res.get(ResourceFF, 0) res[ResourceFF] = ffs + w self.resource_for_object[ff] = (ResourceFF, w)
[docs] def registerLatch(self, latch: RtlSignal): res = self.resources w = latch._dtype.bit_length() latches = res.get(ResourceLatch, 0) res[ResourceLatch] = latches + w self.resource_for_object[latch] = (ResourceLatch, w)
[docs] def registerRAM_write_port(self, mem: RtlSignal, addr: RtlSignal, synchronous: bool): res = self.memories addresses = res.get(mem, {}) res[mem] = addresses # [rSycn, wSync, rAsync, wAsync] portCnts = addresses.get(addr, [0, 0, 0, 0]) if synchronous: portCnts[1] += 1 else: portCnts[3] += 1 addresses[addr] = portCnts
[docs] def registerRAM_read_port(self, mem: RtlSignal, addr: RtlSignal, synchronous: bool): res = self.memories addresses = res.get(mem, {}) res[mem] = addresses # [rSycn, wSync, rAsync, wAsync] portCnts = addresses.get(addr, [0, 0, 0, 0]) if synchronous: portCnts[0] += 1 else: portCnts[2] += 1 addresses[addr] = portCnts
[docs] def finalize(self): """ Resolve ports of discovered memories """ ff_to_remove = 0 res = self.resources for m, addrDict in self.memories.items(): rwSyncPorts, rSyncPorts, wSyncPorts = 0, 0, 0 rwAsyncPorts, rAsyncPorts, wAsyncPorts = 0, 0, 0 rSync_wAsyncPorts, rAsync_wSyncPorts = 0, 0 for _, (rSync, wSync, rAsync, wAsync) in addrDict.items(): if rSync: ff_to_remove += rSync * m._dtype.element_t.bit_length() # resolve port count for this addr signal rwSync = min(rSync, wSync) rSync -= rwSync wSync -= rwSync rwAsync = min(rAsync, wAsync) rAsync -= rwAsync wAsync -= rwAsync rSync_wAsync = min(rSync, wAsync) rSync -= rSync_wAsync wAsync -= rSync_wAsync rAsync_wSync = min(rAsync, wSync) rAsync -= rAsync_wSync wSync -= rAsync_wSync # update port counts for mem rwSyncPorts += rwSync rSyncPorts += rSync wSyncPorts += wSync rwAsyncPorts += rwAsync rAsyncPorts += rAsync wAsyncPorts += wAsync rSync_wAsyncPorts += rSync_wAsync rAsync_wSyncPorts += rAsync_wSync k = ResourceRAM(m._dtype.element_t.bit_length(), int(m._dtype.size), rwSyncPorts, rSyncPorts, wSyncPorts, rSync_wAsyncPorts, rwAsyncPorts, rAsyncPorts, wAsyncPorts, rAsync_wSyncPorts) res[k] = res.get(k, 0) + 1 self.memories.clear() # remove register on read ports which will be merged into ram if ff_to_remove: ff_cnt = res[ResourceFF] ff_cnt -= ff_to_remove if ff_cnt: res[ResourceFF] = ff_cnt else: del res[ResourceFF]