diff --git a/SDFTools/examples/example1/test.dot b/SDFTools/examples/example1/test.dot index 8a8797ef..4dff5dc5 100755 --- a/SDFTools/examples/example1/test.dot +++ b/SDFTools/examples/example1/test.dot @@ -31,9 +31,17 @@ source [label=< -source:i -> filter:i [headlabel=<7>,taillabel=<5>,label="f32(11)"] - -filter:i -> sink:i [headlabel=<5>,taillabel=<5>,label="f32(5)"] +source:i -> filter:i [headlabel=< +
7 +
>,taillabel=< +
5 +
>,label="f32(11)"] + +filter:i -> sink:i [headlabel=< +
5 +
>,taillabel=< +
5 +
>,label="f32(5)"] } diff --git a/SDFTools/examples/example1/test.pdf b/SDFTools/examples/example1/test.pdf index b3c1f012..82166212 100755 Binary files a/SDFTools/examples/example1/test.pdf and b/SDFTools/examples/example1/test.pdf differ diff --git a/SDFTools/examples/example2/test.dot b/SDFTools/examples/example2/test.dot index dc3a90e0..6bb73e30 100755 --- a/SDFTools/examples/example2/test.dot +++ b/SDFTools/examples/example2/test.dot @@ -23,13 +23,13 @@ arm_add_f321 [label=< arm_add_f32
(CMSIS-DSP) o - + ib - - ->]; + + +>]; arm_scale_f321 [label=< @@ -39,13 +39,13 @@ arm_scale_f321 [label=< arm_scale_f32
(CMSIS-DSP) o - + ib - - ->]; + + +>]; arm_scale_f322 [label=< @@ -55,13 +55,13 @@ arm_scale_f322 [label=< arm_scale_f32
(CMSIS-DSP) o - + ib - - ->]; + + +>]; audioWin [label=< @@ -99,7 +99,8 @@ toMono [label=< - + + @@ -107,7 +108,6 @@ toMono [label=<
toMono
(Unzip)
o1
o2
>]; - srcDelay [label=< @@ -116,26 +116,62 @@ srcDelay [label=<
>]; -src:i -> srcDelay:i [taillabel=<320>] - -srcDelay:i -> toMono:i [headlabel=<320>,label="f32(330)"] - - -toMono:o1 -> arm_scale_f321:ia [headlabel=<160>,taillabel=<160>,label="f32(160)"] - -toMono:o2 -> arm_scale_f322:ia [headlabel=<160>,taillabel=<160>,label="f32(160)"] - -arm_scale_f321:o -> arm_add_f321:ia [headlabel=<160>,taillabel=<160>,label="f32(160)"] - -arm_scale_f322:o -> arm_add_f321:ib [headlabel=<160>,taillabel=<160>,label="f32(160)"] - -arm_add_f321:o -> audioWin:i [headlabel=<320>,taillabel=<160>,label="f32(320)"] - -audioWin:i -> mfcc:i [headlabel=<640>,taillabel=<640>,label="f32(640)"] - -mfcc:i -> mfccWind:i [headlabel=<250>,taillabel=<10>,label="f32(250)"] - -mfccWind:i -> TFLite:i [headlabel=<500>,taillabel=<500>,label="f32(500)"] +src:i -> srcDelay:i [taillabel=< +
320 +
>] + +srcDelay:i -> toMono:i [headlabel=< +
320 +
>,label="f32(330)"] + + +toMono:o1 -> arm_scale_f321:ia [headlabel=< +
160 +
>,taillabel=< +
160 +
>,label="f32(160)"] + +toMono:o2 -> arm_scale_f322:ia [headlabel=< +
160 +
>,taillabel=< +
160 +
>,label="f32(160)"] + +arm_scale_f321:o -> arm_add_f321:ia [headlabel=< +
160 +
>,taillabel=< +
160 +
>,label="f32(160)"] + +arm_scale_f322:o -> arm_add_f321:ib [headlabel=< +
160 +
>,taillabel=< +
160 +
>,label="f32(160)"] + +arm_add_f321:o -> audioWin:i [headlabel=< +
320 +
>,taillabel=< +
160 +
>,label="f32(320)"] + +audioWin:i -> mfcc:i [headlabel=< +
640 +
>,taillabel=< +
640 +
>,label="f32(640)"] + +mfcc:i -> mfccWind:i [headlabel=< +
250 +
>,taillabel=< +
10 +
>,label="f32(250)"] + +mfccWind:i -> TFLite:i [headlabel=< +
500 +
>,taillabel=< +
500 +
>,label="f32(500)"] HALF [label=< diff --git a/SDFTools/examples/example2/test.pdf b/SDFTools/examples/example2/test.pdf index 38415ac6..485a0e51 100755 Binary files a/SDFTools/examples/example2/test.pdf and b/SDFTools/examples/example2/test.pdf differ diff --git a/SDFTools/examples/example3/test.dot b/SDFTools/examples/example3/test.dot index 4c072ec7..87632a28 100755 --- a/SDFTools/examples/example3/test.dot +++ b/SDFTools/examples/example3/test.dot @@ -16,13 +16,13 @@ arm_mult_f321 [label=< - + - - -
arm_mult_f32
(CMSIS-DSP)
o
ib
>]; + + +>]; audioOverlap [label=< @@ -82,21 +82,53 @@ toReal [label=< -src:i -> audioWin:i [headlabel=<128>,taillabel=<192>,label="f32(256)"] - -audioWin:i -> arm_mult_f321:ia [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -arm_mult_f321:o -> toCmplx:i [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -toCmplx:i -> cfft:i [headlabel=<512>,taillabel=<512>,label="f32(512)"] - -cfft:i -> icfft:i [headlabel=<512>,taillabel=<512>,label="f32(512)"] - -icfft:i -> toReal:i [headlabel=<512>,taillabel=<512>,label="f32(512)"] - -toReal:i -> audioOverlap:i [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -audioOverlap:i -> sink:i [headlabel=<192>,taillabel=<128>,label="f32(256)"] +src:i -> audioWin:i [headlabel=< +
128 +
>,taillabel=< +
192 +
>,label="f32(256)"] + +audioWin:i -> arm_mult_f321:ia [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +arm_mult_f321:o -> toCmplx:i [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +toCmplx:i -> cfft:i [headlabel=< +
512 +
>,taillabel=< +
512 +
>,label="f32(512)"] + +cfft:i -> icfft:i [headlabel=< +
512 +
>,taillabel=< +
512 +
>,label="f32(512)"] + +icfft:i -> toReal:i [headlabel=< +
512 +
>,taillabel=< +
512 +
>,label="f32(512)"] + +toReal:i -> audioOverlap:i [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +audioOverlap:i -> sink:i [headlabel=< +
192 +
>,taillabel=< +
128 +
>,label="f32(256)"] HANN [label=< diff --git a/SDFTools/examples/example3/test.pdf b/SDFTools/examples/example3/test.pdf index c4360537..5c1db1b7 100755 Binary files a/SDFTools/examples/example3/test.pdf and b/SDFTools/examples/example3/test.pdf differ diff --git a/SDFTools/examples/example4/test.dot b/SDFTools/examples/example4/test.dot index 4c072ec7..87632a28 100755 --- a/SDFTools/examples/example4/test.dot +++ b/SDFTools/examples/example4/test.dot @@ -16,13 +16,13 @@ arm_mult_f321 [label=< - + - - -
arm_mult_f32
(CMSIS-DSP)
o
ib
>]; + + +>]; audioOverlap [label=< @@ -82,21 +82,53 @@ toReal [label=< -src:i -> audioWin:i [headlabel=<128>,taillabel=<192>,label="f32(256)"] - -audioWin:i -> arm_mult_f321:ia [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -arm_mult_f321:o -> toCmplx:i [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -toCmplx:i -> cfft:i [headlabel=<512>,taillabel=<512>,label="f32(512)"] - -cfft:i -> icfft:i [headlabel=<512>,taillabel=<512>,label="f32(512)"] - -icfft:i -> toReal:i [headlabel=<512>,taillabel=<512>,label="f32(512)"] - -toReal:i -> audioOverlap:i [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -audioOverlap:i -> sink:i [headlabel=<192>,taillabel=<128>,label="f32(256)"] +src:i -> audioWin:i [headlabel=< +
128 +
>,taillabel=< +
192 +
>,label="f32(256)"] + +audioWin:i -> arm_mult_f321:ia [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +arm_mult_f321:o -> toCmplx:i [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +toCmplx:i -> cfft:i [headlabel=< +
512 +
>,taillabel=< +
512 +
>,label="f32(512)"] + +cfft:i -> icfft:i [headlabel=< +
512 +
>,taillabel=< +
512 +
>,label="f32(512)"] + +icfft:i -> toReal:i [headlabel=< +
512 +
>,taillabel=< +
512 +
>,label="f32(512)"] + +toReal:i -> audioOverlap:i [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +audioOverlap:i -> sink:i [headlabel=< +
192 +
>,taillabel=< +
128 +
>,label="f32(256)"] HANN [label=< diff --git a/SDFTools/examples/example4/test.pdf b/SDFTools/examples/example4/test.pdf index c4360537..5c1db1b7 100755 Binary files a/SDFTools/examples/example4/test.pdf and b/SDFTools/examples/example4/test.pdf differ diff --git a/SDFTools/examples/example5/test.dot b/SDFTools/examples/example5/test.dot index 2bbf4bd7..b28b8dee 100755 --- a/SDFTools/examples/example5/test.dot +++ b/SDFTools/examples/example5/test.dot @@ -52,15 +52,35 @@ toMono [label=< -src:i -> toMono:i [headlabel=<384>,taillabel=<384>,label="q15(384)"] - -toMono:i -> audioWin:i [headlabel=<768>,taillabel=<192>,label="q15(768)"] - -audioWin:i -> mfcc:i [headlabel=<1024>,taillabel=<1024>,label="q15(1024)"] - -mfcc:i -> mfccWin:i [headlabel=<377>,taillabel=<13>,label="q15(377)"] - -mfccWin:i -> sink:i [headlabel=<754>,taillabel=<754>,label="q15(754)"] +src:i -> toMono:i [headlabel=< +
384 +
>,taillabel=< +
384 +
>,label="q15(384)"] + +toMono:i -> audioWin:i [headlabel=< +
768 +
>,taillabel=< +
192 +
>,label="q15(768)"] + +audioWin:i -> mfcc:i [headlabel=< +
1024 +
>,taillabel=< +
1024 +
>,label="q15(1024)"] + +mfcc:i -> mfccWin:i [headlabel=< +
377 +
>,taillabel=< +
13 +
>,label="q15(377)"] + +mfccWin:i -> sink:i [headlabel=< +
754 +
>,taillabel=< +
754 +
>,label="q15(754)"] } diff --git a/SDFTools/examples/example5/test.pdf b/SDFTools/examples/example5/test.pdf index bac671a5..ce5864fb 100755 Binary files a/SDFTools/examples/example5/test.pdf and b/SDFTools/examples/example5/test.pdf differ diff --git a/SDFTools/examples/example6/test.dot b/SDFTools/examples/example6/test.dot index 5d03f6b6..76451a60 100755 --- a/SDFTools/examples/example6/test.dot +++ b/SDFTools/examples/example6/test.dot @@ -45,13 +45,29 @@ src [label=< -src:i -> audioWin:i [headlabel=<128>,taillabel=<192>,label="f32(256)"] - -audioWin:i -> mfcc:i [headlabel=<256>,taillabel=<256>,label="f32(256)"] - -mfcc:i -> mfccWin:i [headlabel=<13>,taillabel=<13>,label="f32(13)"] - -mfccWin:i -> sink:i [headlabel=<13>,taillabel=<26>,label="f32(26)"] +src:i -> audioWin:i [headlabel=< +
128 +
>,taillabel=< +
192 +
>,label="f32(256)"] + +audioWin:i -> mfcc:i [headlabel=< +
256 +
>,taillabel=< +
256 +
>,label="f32(256)"] + +mfcc:i -> mfccWin:i [headlabel=< +
13 +
>,taillabel=< +
13 +
>,label="f32(13)"] + +mfccWin:i -> sink:i [headlabel=< +
13 +
>,taillabel=< +
26 +
>,label="f32(26)"] } diff --git a/SDFTools/examples/example6/test.pdf b/SDFTools/examples/example6/test.pdf index dcf9b4c8..f4c0c35b 100755 Binary files a/SDFTools/examples/example6/test.pdf and b/SDFTools/examples/example6/test.pdf differ diff --git a/SDFTools/sdf/schedule/config.py b/SDFTools/sdf/schedule/config.py index ae47021a..1a7afc6d 100755 --- a/SDFTools/sdf/schedule/config.py +++ b/SDFTools/sdf/schedule/config.py @@ -68,6 +68,9 @@ class Configuration: # True for an horizontal graphviz layout self.horizontal = True + # Display FIFO buffers in graph instead of datatype + self.displayFIFOBuf = False + @property def debug(self): return (self.debugLimit > 0) diff --git a/SDFTools/sdf/schedule/description.py b/SDFTools/sdf/schedule/description.py index 3e14729f..c276fbaf 100755 --- a/SDFTools/sdf/schedule/description.py +++ b/SDFTools/sdf/schedule/description.py @@ -40,6 +40,9 @@ from sdf.schedule.node import * from sdf.schedule.config import * from sdf.schedule.types import * +# To debug graph coloring for memory optimization +#import matplotlib.pyplot as plt + class IncompatibleIO(Exception): pass @@ -67,16 +70,14 @@ class FIFODesc: def __init__(self,fifoid): # The FIFO is in fact just an array self.isArray=False - # Max distance between a write and a read to the FIFO - # If it is 1, data written to FIFO - # is immediately read so buffer can be reused - self.distance=1 # FIFO length self.length=0 # FIFO type self.theType=None # Buffer used by FIFO self.buffer=None + # Used for plot in graphviz + self.bufferID=-1 self._fifoID=fifoid # Source IO self.src = None @@ -84,15 +85,16 @@ class FIFODesc: self.dst = None # FIFO delay self.delay=0 - # Can use a shared buffer ? - self.isShared = False - - self._writeTime= 0 - # Track when FIFO is used - # For allocation of shared buffers we need - # to know when 2 buffers are used at same time - self._timeOfUse=[] + # Used for liveliness analysis + # To share buffers between FIFO in memory optimization + # mode, we need to know when a FIFO is in use. + # We compute the maximum extent : so the biggest interval + # and not a disconnected union of intervals + # This could be improved. We could use + # a disjoint union of intervals but they should be mapped + # to the same node in the interference graph + self._liveInterval=(-1,-1) # shared buffer number not yet allocated self.sharedNB=-1 @@ -110,36 +112,31 @@ class FIFODesc: return(self.delay>0) def dump(self): - shared=0 - if self.isShared: - shared=1 - print("array %d dist %d len %d %s id %d src %s:%s dst %s:%s shared:%d" % + + print("array %d len %d %s id %d src %s:%s dst %s:%s " % (self.isArray, - self.distance, self.length, self.theType.ctype, self.fifoID, self.src.owner.nodeID, self.src.name, self.dst.owner.nodeID, - self.dst.name, - shared)) + self.dst.name)) @property def fifoID(self): return self._fifoID def recordWrite(self,theTime): - self._timeOfUse.append(theTime) - if self._writeTime == 0: - self._writeTime = theTime + start,stop=self._liveInterval + if start==-1: + self._liveInterval=(theTime,stop) def recordRead(self,theTime): - self._timeOfUse.append(theTime) - delta = theTime - self._writeTime - self._writeTime = 0 - if delta > self.distance: - self.distance = delta + start,stop=self._liveInterval + if (theTime > stop): + self._liveInterval=(start,theTime) + def analyzeStep(vec,allFIFOs,theTime): """Analyze an evolution step to know which FIFOs are read and written to""" @@ -209,7 +206,7 @@ class Graph(): return(res) - def initializeFIFODescriptions(self,config,allFIFOs, fifoLengths): + def initializeFIFODescriptions(self,config,allFIFOs, fifoLengths,maxTime): """Initialize FIFOs datastructure""" for fifo in allFIFOs: edge = self._sortedEdges[fifo.fifoID] @@ -218,113 +215,126 @@ class Graph(): fifo.src=src fifo.dst=dst fifo.delay=self.getDelay(edge) + # When a FIFO is working as an array then its buffer may + # potentially be shared with other FIFOs workign as arrays if src.nbSamples == dst.nbSamples: if fifo.delay==0: fifo.isArray = True - if fifo.distance==1: - if fifo.delay==0: - fifo.isShared = True fifo.theType = src.theType #fifo.dump() - # When we have bufA -> Node -> bufB then - # bufA and bufB can't share the same memory. - # For the allocation of shared buffer we scan all times - # of use and for each time we look at the FIFOs which - # can be potentially shared. + bufferID=0 + allBuffers=[] - # For each time of use, record the potentially shareable fifos - # which are used - fifoForTime={} - for fifo in allFIFOs: - if fifo.isShared: - for t in fifo._timeOfUse: - if t in fifoForTime: - fifoForTime[t].append(fifo) - else: - fifoForTime[t]=[fifo] - - # If several shareable FIFOs are used at same time, they - # must be assigned to different shared buffers if possible - usedAtSameTime={} - for t in sorted(fifoForTime.keys()): - if len(fifoForTime[t])>2: - # This case is not managed in this version. - # It could occur with quadripoles for instance - for fifo in fifoForTime[t]: - fifo.isShared=False - elif len(fifoForTime[t])==2: - # 2 FIFOs are used at the same time - fifoA = fifoForTime[t][0] - fifoB = fifoForTime[t][1] - if fifoA.sharedNB >= 0 and fifoA.sharedNB == fifoB.sharedNB: - # Those FIFOs are already both assigned to a buffer - # and we can't reassign and they use the same buffer - # So we can't consistently associate shared buffers to those - # FIFOs - fifoA.isShared=False - fifoB.isShared=False - else: - # The 2 FIFOs were never associated with a shared buffer - if fifoA.sharedNB < 0 and fifoB.sharedNB < 0: - fifoA.sharedNB=0 - fifoB.sharedNB=1 - # One FIFO is associated, so we associate the other one - # to the other shared buffer - elif fifoA.sharedNB < 0: - fifoA.sharedNB = 1 - fifoB.sharedNB - else: - fifoB.sharedNB = 1 - fifoA.sharedNB - else: - fifoA = fifoForTime[t][0] - if fifoA.sharedNB < 0: - fifoA.sharedNB = 0 - + # Compute a graph describing when FIFOs are used at the same time + # The use graph coloring to allocate buffer to those FIFOs. + # Then size the buffer based on the longest FIFO using it + if config.memoryOptimization: + G = nx.Graph() + + for fifo in allFIFOs: + if fifo.isArray: + G.add_node(fifo) + + # Create the interference graph + + # Dictionary of active FIFOs at a given time. + # The time is a scheduling step + active={} + currentTime=0 + while currentTime<=maxTime: + # Remove fifo no more active. + # Thei stop time < currenTime + toDelete=[] + for k in active: + start,stop=k._liveInterval + if stop node -> dst + # At time t, node will read for src and the stop time + # will be currentTime t. + # And it will write to dst and the start time will be + # currentTime + # So, src and dst are both live at this time. + # Which means the condition on the stop time must be + # stop >= currentTime and not a strict comparison + if start<=currentTime and stop >= currentTime: + if not (fifo in active): + for k in active: + G.add_edge(k,fifo) + active[fifo]=True + + currentTime = currentTime + 1 + + # To debug and display the graph + if False: + labels={} + for n in G.nodes: + labels[n]="%s -> %s" % (n.src.owner.nodeName,n.dst.owner.nodeName) + + pos = nx.spring_layout(G, seed=3113794652) + subax1 = plt.subplot(121) + nx.draw_networkx_edges(G, pos, width=1.0, alpha=0.5) + + nx.draw_networkx_labels(G, pos, labels, font_size=10) + plt.show() + quit() + + # Graph coloring + d = nx.coloring.greedy_color(G, strategy="largest_first") + + # Allocate the colors (buffer ID) to the FIFO + # and keep track of the max color number + # Since other buffers (for real FIFOs) will have their + # numbering start after this one. + for fifo in d: + fifo.sharedNB=d[fifo] + bufferID=max(bufferID,fifo.sharedNB) - # Now we create buffers - maxSharedA=0 - maxSharedB=0 - allBuffers=[] - for fifo in allFIFOs: - lengthInBytes = fifo.theType.bytes * fifo.length - if fifo.isShared: - if fifo.sharedNB == 0: - if lengthInBytes > maxSharedA: - maxSharedA = lengthInBytes - if fifo.sharedNB == 1: - if lengthInBytes > maxSharedB: - maxSharedB = lengthInBytes - bufferID=0 - sharedA=None - sharedB=None - if maxSharedA > 0 and config.memoryOptimization: - # Create the shared buffer if memory optimization on - sharedA = FifoBuffer(bufferID,CType(UINT8),maxSharedA) - allBuffers.append(sharedA) - bufferID = bufferID + 1 - - if maxSharedB > 0 and config.memoryOptimization: - # Create the shared buffer if memory optimization on - sharedB = FifoBuffer(bufferID,CType(UINT8),maxSharedB) - allBuffers.append(sharedB) - bufferID = bufferID + 1 + + # Compute the max size for each shared buffer + maxSizes={} + for fifo in d: + lengthInBytes = fifo.theType.bytes * fifo.length + if fifo.sharedNB in maxSizes: + maxSizes[fifo.sharedNB] = max(maxSizes[fifo.sharedNB],lengthInBytes) + else: + maxSizes[fifo.sharedNB]=lengthInBytes + + # Create the buffers + for theID in maxSizes: + sharedA = FifoBuffer(theID,CType(UINT8),maxSizes[theID]) + allBuffers.append(sharedA) for fifo in allFIFOs: # Use shared buffer if memory optimization - if fifo.isShared and config.memoryOptimization: - if fifo.sharedNB == 0: - fifo.buffer=sharedA - else: - fifo.buffer=sharedB + if fifo.isArray and config.memoryOptimization: + fifo.buffer=allBuffers[fifo.sharedNB] + fifo.bufferID=fifo.sharedNB + # Create a new buffer for a real FIFO + # Use bufferID which is starting after the numbers allocated + # to shared buffers else: buf = FifoBuffer(bufferID,fifo.theType,fifo.length) allBuffers.append(buf) fifo.buffer=buf + fifo.bufferID = bufferID bufferID = bufferID + 1 + # Compute the total memory used in bytes self._totalMemory = 0 for buf in allBuffers: self._totalMemory = self._totalMemory + buf._theType.bytes * buf._length @@ -529,7 +539,7 @@ class Graph(): fifoMax=np.floor(bMax).astype(np.int32) - allBuffers=self.initializeFIFODescriptions(config,allFIFOs,fifoMax) + allBuffers=self.initializeFIFODescriptions(config,allFIFOs,fifoMax,evolutionTime) self._allFIFOs = allFIFOs self._allBuffers = allBuffers return(Schedule(self,self._sortedNodes,self._sortedEdges,schedule)) diff --git a/SDFTools/sdf/templates/dot_template.dot b/SDFTools/sdf/templates/dot_template.dot index ce22313e..abfa5a74 100755 --- a/SDFTools/sdf/templates/dot_template.dot +++ b/SDFTools/sdf/templates/dot_template.dot @@ -115,10 +115,23 @@ digraph structs {
{{fifos[id].src.nbSamples}}
>] +{% if config.displayFIFOBuf %} +{{delayBoxID(id)}}:i -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=< +
{{fifos[id].dst.nbSamples}} +
>,label="buf{{fifos[id].bufferID}}"] +{% else %} {{delayBoxID(id)}}:i -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=<
{{fifos[id].dst.nbSamples}}
>,label="{{fifos[id].theType.graphViztype}}({{fifos[id].length}})"] +{% endif %} +{% else %} +{% if config.displayFIFOBuf %} +{{io(fifos[id].src.owner,fifos[id].src)}} -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=< +
{{fifos[id].dst.nbSamples}} +
>,taillabel=< +
{{fifos[id].src.nbSamples}} +
>,label="buf{{fifos[id].bufferID}}"] {% else %} {{io(fifos[id].src.owner,fifos[id].src)}} -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=<
{{fifos[id].dst.nbSamples}} @@ -126,6 +139,7 @@ digraph structs {
{{fifos[id].src.nbSamples}}
>,label="{{fifos[id].theType.graphViztype}}({{fifos[id].length}})"] {% endif %} +{% endif %} {% endfor %} {% for c in constObjs %}