SDF now support connection to multiple outputs.

Duplicate nodes are inserted automatically.
pull/53/head
Christophe Favergeon 3 years ago
parent ea509ff389
commit a11e026e4f

@ -74,17 +74,29 @@ public:
};
template<typename IN, int inputSize,typename OUT,int outputSize>
class ProcessingNode: public GenericNode<IN,inputSize,OUT,outputSize>
template<typename IN, int inputSize,
typename OUT1,int outputSize1,
typename OUT2,int outputSize2>
class ProcessingNode: public GenericNode12<IN,inputSize,
OUT1,outputSize1,
OUT2,outputSize2>
{
public:
ProcessingNode(FIFOBase<IN> &src,FIFOBase<OUT> &dst,int,const char*,int):GenericNode<IN,inputSize,OUT,outputSize>(src,dst){};
ProcessingNode(FIFOBase<IN> &src,
FIFOBase<OUT1> &dst1,
FIFOBase<OUT2> &dst2,
int,const char*,int):
GenericNode12<IN,inputSize,
OUT1,outputSize1,
OUT2,outputSize2>(src,dst1,dst2){};
int run(){
printf("ProcessingNode\n");
IN *a=this->getReadBuffer();
OUT *b=this->getWriteBuffer();
b[0] =(OUT)a[3];
OUT1 *b=this->getWriteBuffer1();
OUT2 *c=this->getWriteBuffer2();
b[0] =(OUT1)a[3];
c[0] =(OUT2)a[3];
return(0);
};

@ -44,14 +44,15 @@ class Sink(GenericSink):
print("%f + I %f" % (c.re,c.im))
return(0)
class ProcessingNode(GenericNode):
def __init__(self,inputSize,outputSize,fifoin,fifoout,i,s,v):
GenericNode.__init__(self,inputSize,outputSize,fifoin,fifoout)
class ProcessingNode(GenericNode12):
def __init__(self,inputSize,outputSize1,outputSize2,fifoin,fifoout1,fifoout2,i,s,v):
GenericNode12.__init__(self,inputSize,outputSize1,outputSize2,fifoin,fifoout1,fifoout2)
def run(self):
print("ProcessingNode");
a=self.getReadBuffer()
b=self.getWriteBuffer()
b=self.getWriteBuffer1()
c=self.getWriteBuffer2()
# Python objects have reference semantic and not
# value semantic.
# So in a write buffer, we can change the
@ -59,6 +60,7 @@ class ProcessingNode(GenericNode):
# replace the object and risk creating sharing
# Duplicating the a object may be ok
b[0]=a[3]
c[0]=a[3]
return(0)
class Source(GenericSource):

@ -24,6 +24,7 @@ FIFO buffers
#define FIFOSIZE2 5
#define FIFOSIZE3 5
#define FIFOSIZE4 5
#define FIFOSIZE5 5
#define BUFFERSIZE0 11
complex buf0[BUFFERSIZE0]={0};
@ -40,6 +41,9 @@ complex buf3[BUFFERSIZE3]={0};
#define BUFFERSIZE4 5
complex buf4[BUFFERSIZE4]={0};
#define BUFFERSIZE5 5
complex buf5[BUFFERSIZE5]={0};
uint32_t scheduler(int *error,int someVariable)
{
@ -55,15 +59,17 @@ uint32_t scheduler(int *error,int someVariable)
FIFO<complex,FIFOSIZE2,1> fifo2(buf2);
FIFO<complex,FIFOSIZE3,1> fifo3(buf3);
FIFO<complex,FIFOSIZE4,1> fifo4(buf4);
FIFO<complex,FIFOSIZE5,1> fifo5(buf5);
/*
Create node objects
*/
Duplicate3<complex,5,complex,5,complex,5,complex,5> dup(fifo1,fifo2,fifo3,fifo4);
ProcessingNode<complex,7,complex,5> filter(fifo0,fifo1,4,"Test",someVariable);
Sink<complex,5> sa(fifo2);
Sink<complex,5> sb(fifo3);
Sink<complex,5> sc(fifo4);
Duplicate3<complex,5,complex,5,complex,5,complex,5> dup0(fifo2,fifo3,fifo4,fifo5);
ProcessingNode<complex,7,complex,5,complex,5> filter(fifo0,fifo2,fifo1,4,"Test",someVariable);
Sink<complex,5> sa(fifo3);
Sink<complex,5> sb(fifo4);
Sink<complex,5> sc(fifo5);
Sink<complex,5> sd(fifo1);
Source<complex,5> source(fifo0);
/* Run several schedule iterations */
@ -76,7 +82,9 @@ uint32_t scheduler(int *error,int someVariable)
CHECKERROR;
sdfError = filter.run();
CHECKERROR;
sdfError = dup.run();
sdfError = sd.run();
CHECKERROR;
sdfError = dup0.run();
CHECKERROR;
sdfError = sc.run();
CHECKERROR;
@ -90,7 +98,9 @@ uint32_t scheduler(int *error,int someVariable)
CHECKERROR;
sdfError = source.run();
CHECKERROR;
sdfError = dup.run();
sdfError = sd.run();
CHECKERROR;
sdfError = dup0.run();
CHECKERROR;
sdfError = sc.run();
CHECKERROR;
@ -102,7 +112,9 @@ uint32_t scheduler(int *error,int someVariable)
CHECKERROR;
sdfError = filter.run();
CHECKERROR;
sdfError = dup.run();
sdfError = sd.run();
CHECKERROR;
sdfError = dup0.run();
CHECKERROR;
sdfError = sc.run();
CHECKERROR;
@ -116,7 +128,9 @@ uint32_t scheduler(int *error,int someVariable)
CHECKERROR;
sdfError = source.run();
CHECKERROR;
sdfError = dup.run();
sdfError = sd.run();
CHECKERROR;
sdfError = dup0.run();
CHECKERROR;
sdfError = sc.run();
CHECKERROR;
@ -126,7 +140,9 @@ uint32_t scheduler(int *error,int someVariable)
CHECKERROR;
sdfError = filter.run();
CHECKERROR;
sdfError = dup.run();
sdfError = sd.run();
CHECKERROR;
sdfError = dup0.run();
CHECKERROR;
sdfError = sc.run();
CHECKERROR;

@ -6,7 +6,8 @@ class Node(GenericNode):
def __init__(self,name,theType,inLength,outLength):
GenericNode.__init__(self,name)
self.addInput("i",theType,inLength)
self.addOutput("o",theType,outLength)
self.addOutput("oa",theType,outLength)
self.addOutput("ob",theType,outLength)
class Sink(GenericSink):
def __init__(self,name,theType,inLength):
@ -52,44 +53,54 @@ b.addVariableArg("someVariable")
na = Sink("sa",complexType,5)
nb = Sink("sb",complexType,5)
nc = Sink("sc",complexType,5)
dup=Duplicate3("dup",complexType,5)
nd = Sink("sd",complexType,5)
#dup=Duplicate3("dup",complexType,5)
g = Graph()
g.connect(src.o,b.i)
g.connect(b.o,dup.i)
g.connect(dup.oa,na.i)
g.connect(dup.ob,nb.i)
g.connect(dup.oc,nc.i)
#g.connect(b.o,dup.i)
#g.connect(dup.oa,na.i)
#g.connect(dup.ob,nb.i)
#g.connect(dup.oc,nc.i)
g.connect(b.oa,na.i)
g.connect(b.oa,nb.i)
g.connect(b.oa,nc.i)
g.connect(b.ob,nd.i)
GEN_PYTHON = False
print("Generate graphviz and code")
sched = g.computeSchedule()
print("Schedule length = %d" % sched.scheduleLength)
print("Memory usage %d bytes" % sched.memory)
# Generation of the schedule is modifying the original graph
# (Introduction of duplicate nodes ...)
# So we cannot reuse the graph to compute the Python and the C
# code generation
conf=Configuration()
conf.debugLimit=1
conf.cOptionalArgs="int someVariable"
#conf.displayFIFOSizes=True
# Prefix for global FIFO buffers
#conf.prefix="sched1"
#print(g.nullVector())
sched1 = g.computeSchedule()
#print(sched.schedule)
print("Schedule length = %d" % sched1.scheduleLength)
print("Memory usage %d bytes" % sched1.memory)
#
#conf.codeArray=True
# C++ implementation
sched1.ccode("generated",conf)
conf.memoryOptimization=True
if not GEN_PYTHON:
# C++ implementation
sched.ccode("generated",conf)
else:
# Python implementation
conf.pyOptionalArgs="someVariable"
sched.pythoncode(".",config=conf)
sched2 = g.computeSchedule()
# Python implementation
#conf.prefix="sched1"
conf.pyOptionalArgs="someVariable"
#conf.dumpFIFO=True
sched2.pythoncode(".",config=conf)
# When true it is displaying the name of the FIFO buffer
# When false it is displaying the size of the FIFO (default)
conf.displayFIFOBuf=False
with open("test.dot","w") as f:
sched1.graphviz(f)
sched.graphviz(f,config=conf)

@ -51,6 +51,12 @@ buf4=np.empty(FIFOSIZE4,dtype=object)
for i in range(FIFOSIZE4):
buf4[i] = MyComplex()
FIFOSIZE5=5
buf5=np.empty(FIFOSIZE5,dtype=object)
for i in range(FIFOSIZE5):
buf5[i] = MyComplex()
def scheduler(someVariable):
sdfError=0
@ -65,15 +71,17 @@ def scheduler(someVariable):
fifo2=FIFO(FIFOSIZE2,buf2)
fifo3=FIFO(FIFOSIZE3,buf3)
fifo4=FIFO(FIFOSIZE4,buf4)
fifo5=FIFO(FIFOSIZE5,buf5)
#
# Create node objects
#
dup = Duplicate3(5,5,5,5,fifo1,fifo2,fifo3,fifo4)
filter = ProcessingNode(7,5,fifo0,fifo1,4,"Test",someVariable)
sa = Sink(5,fifo2)
sb = Sink(5,fifo3)
sc = Sink(5,fifo4)
dup0 = Duplicate3(5,5,5,5,fifo2,fifo3,fifo4,fifo5)
filter = ProcessingNode(7,5,5,fifo0,fifo2,fifo1,4,"Test",someVariable)
sa = Sink(5,fifo3)
sb = Sink(5,fifo4)
sc = Sink(5,fifo5)
sd = Sink(5,fifo1)
source = Source(5,fifo0)
while((sdfError==0) and (debugCounter > 0)):
@ -88,7 +96,10 @@ def scheduler(someVariable):
sdfError = filter.run()
if sdfError < 0:
break
sdfError = dup.run()
sdfError = sd.run()
if sdfError < 0:
break
sdfError = dup0.run()
if sdfError < 0:
break
sdfError = sc.run()
@ -109,7 +120,10 @@ def scheduler(someVariable):
sdfError = source.run()
if sdfError < 0:
break
sdfError = dup.run()
sdfError = sd.run()
if sdfError < 0:
break
sdfError = dup0.run()
if sdfError < 0:
break
sdfError = sc.run()
@ -127,7 +141,10 @@ def scheduler(someVariable):
sdfError = filter.run()
if sdfError < 0:
break
sdfError = dup.run()
sdfError = sd.run()
if sdfError < 0:
break
sdfError = dup0.run()
if sdfError < 0:
break
sdfError = sc.run()
@ -148,7 +165,10 @@ def scheduler(someVariable):
sdfError = source.run()
if sdfError < 0:
break
sdfError = dup.run()
sdfError = sd.run()
if sdfError < 0:
break
sdfError = dup0.run()
if sdfError < 0:
break
sdfError = sc.run()
@ -163,7 +183,10 @@ def scheduler(someVariable):
sdfError = filter.run()
if sdfError < 0:
break
sdfError = dup.run()
sdfError = sd.run()
if sdfError < 0:
break
sdfError = dup0.run()
if sdfError < 0:
break
sdfError = sc.run()

@ -1,6 +1,7 @@
digraph structs {
node [shape=plaintext]
rankdir=LR
@ -8,33 +9,24 @@ digraph structs {
fontname="times"
dup0 [shape=point,label=dup0]
dup [label=<
filter [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD PORT="i"><FONT POINT-SIZE="9.0">i</FONT></TD>
<TD ALIGN="CENTER" ROWSPAN="3">dup<BR/>(Duplicate3)</TD>
<TD ALIGN="CENTER" ROWSPAN="2">filter<BR/>(ProcessingNode)</TD>
<TD PORT="oa"><FONT POINT-SIZE="9.0">oa</FONT></TD>
</TR>
<TR>
<TD></TD>
<TD PORT="ob"><FONT POINT-SIZE="9.0">ob</FONT></TD>
</TR><TR>
<TD></TD>
<TD PORT="oc"><FONT POINT-SIZE="9.0">oc</FONT></TD>
</TR>
</TABLE>>];
filter [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">filter<BR/>(ProcessingNode)</TD>
</TR>
</TABLE>>];
sa [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
@ -56,6 +48,13 @@ sc [label=<
</TR>
</TABLE>>];
sd [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
<TD ALIGN="CENTER" PORT="i">sd<BR/>(Sink)</TD>
</TR>
</TABLE>>];
source [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR>
@ -65,35 +64,41 @@ source [label=<
source:i -> filter:i [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >7</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,label="complex(11)"]
filter:i -> dup:i [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,label="complex(5)"]
dup:oa -> sa:i [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,label="complex(5)"]
dup:ob -> sb:i [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,label="complex(5)"]
dup:oc -> sc:i [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>,label="complex(5)"]
source:i -> filter:i [label="complex(11)"
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >7</FONT>
</TD></TR></TABLE>>
,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>]
filter:ob -> sd:i [label="complex(5)"
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>
,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>]
filter:oa ->
dup0 [label="complex(5)"
,taillabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>]
dup0 -> sa:i [label="complex(5)"
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>
]
dup0 -> sb:i [label="complex(5)"
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>
]
dup0 -> sc:i [label="complex(5)"
,headlabel=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >5</FONT>
</TD></TR></TABLE>>
]
}

@ -38,6 +38,8 @@ import cmsisdsp.sdf.scheduler.pythoncode
from .node import *
from .config import *
from .standard import Duplicate2,Duplicate3
from ..types import *
# To debug graph coloring for memory optimization
@ -58,6 +60,9 @@ class DeadlockError(Exception):
class CannotDelayConstantError(Exception):
pass
class TooManyNodesOnOutput(Exception):
pass
class FifoBuffer:
"""Buffer used by a FIFO"""
def __init__(self,bufferID,theType,length):
@ -165,7 +170,128 @@ class Graph():
self._allFIFOs = None
self._allBuffers = None
def connect(self,nodea,nodeb):
def connectDup(self,destination,outputIO,theId):
if (destination[theId][1]!=0):
self.connectWithDelay(outputIO,destination[theId][0],destination[theId][1],dupAllowed=False)
else:
self.connect(outputIO,destination[theId][0],dupAllowed=False)
def insertDuplicates(self):
# Insert dup nodes (Duplicate2 and Duplicate3) to
# ensure that an output is connected to only one input
dupNb = 0
# Scan all nodes
allNodes = list(self._g)
for n in allNodes:
# For each nodes, get the IOs
for k in n._outputs.keys():
output = n._outputs[k]
fifo = output.fifo
# Check if the FIFO list has only 1 element
# In this case, we convert it into a value
# since code using the graph is expecting an
# IO to be connected top one and only one other IO
# so the FIFO must be a value and not a list
if len(fifo)==1:
# Extract first element of list
fifo = fifo[0]
fifo[0].fifo = fifo
fifo[1].fifo = fifo
# If the FIFO has more elements, we need to
# restructure the graph and add Duplicate nodes
else:
# Currently the library is only providing
# Duplicate2 and Duplicate3 nodes.
# So an output cannot be connected to more than
# 3 inputs
if (len(fifo)>3):
raise TooManyNodesOnOutput
dup = None
# We extract from the IO the nb of produced
# samples and the data type
# Duplicate will use the same
inputSize = output.nbSamples
theType = output.theType
# We create a duplicate node
if len(fifo)==2:
dup = Duplicate2("dup%d" % dupNb,theType,inputSize)
if len(fifo)==3:
dup = Duplicate3("dup%d" % dupNb,theType,inputSize)
#print(dup)
dupNb = dupNb + 1
# We disconnect all the fifo element (a,b)
# and remember the destination b
# We must rewrite the edges of self._g
# self._edges
# self._nodes
# the node fifo
destinations = []
delays = []
self._sortedNodes = None
self._sortedEdges = None
for f in fifo:
# IO connected to the FIFOs
# nodea is the IO belowing to nodea
# but not the node itself
nodea = f[0]
nodeb = f[1]
if (nodea,nodeb) in self._delays:
delay = self._delays[(nodea,nodeb)]
else:
delay = 0
destinations.append((nodeb,delay))
nodea.fifo=None
nodeb.fifo=None
# Since we are not using a multi graph
# and there no parallel edges, it will
# remove all edges between two nodes.
# But some edges may come from other IO
# and be valid.
# Anyway, those edges are not used
# in the algorithm at all
# Instead we have our own graph with self._edges
# (This script will have to be rewritten in a much
# cleaner way)
self._g.remove_edge(nodea.owner,nodeb.owner)
del self._edges[(nodea,nodeb)]
if (nodea,nodeb) in self._delays:
del self._delays[(nodea,nodeb)]
# Now for each fifo destination we need
# create a new
# connection dup -> b
# And we create a new connection a -> dup
self.connect(output,dup.i,dupAllowed=False)
if len(destinations)==2:
self.connectDup(destinations,dup.oa,0)
self.connectDup(destinations,dup.ob,1)
if len(destinations)==3:
self.connectDup(destinations,dup.oa,0)
self.connectDup(destinations,dup.ob,1)
self.connectDup(destinations,dup.oc,2)
def connect(self,nodea,nodeb,dupAllowed=True):
# When connecting to a constant node we do nothing
# since there is no FIFO in this case
# and it does not participate to the scheduling.
@ -178,8 +304,12 @@ class Graph():
self._sortedEdges = None
self._g.add_edge(nodea.owner,nodeb.owner)
nodea.fifo = (nodea,nodeb)
nodeb.fifo = (nodea,nodeb)
if dupAllowed:
nodea.fifo.append((nodea,nodeb))
nodeb.fifo.append((nodea,nodeb))
else:
nodea.fifo=(nodea,nodeb)
nodeb.fifo=(nodea,nodeb)
self._edges[(nodea,nodeb)]=True
if not (nodea.owner in self._nodes):
self._nodes[nodea.owner]=True
@ -188,12 +318,12 @@ class Graph():
else:
raise IncompatibleIO
def connectWithDelay(self,nodea,nodeb,delay):
def connectWithDelay(self,nodea,nodeb,delay,dupAllowed=True):
# We cannot connect with delay to a constant node
if (isinstance(nodea,Constant)):
raise CannotDelayConstantError
else:
self.connect(nodea,nodeb)
self.connect(nodea,nodeb,dupAllowed=dupAllowed)
self._delays[(nodea,nodeb)] = delay
def __str__(self):
@ -426,7 +556,14 @@ class Graph():
v[nodeID] = 1
return(v)
def computeSchedule(self,config=Configuration()):
# First we must rewrite the graph and insert duplication
# nodes when an ouput is connected to several inputs.
# After this transform, each output should be connected to
# only one output.
self.insertDuplicates()
# Init values
initB = self.initEvolutionVector
initN = self.nullVector()

@ -54,7 +54,7 @@ class IO:
self._nbSamples = nbSamples
self._owner = owner
self._name = name
self._fifo = None
self._fifo = []
self.constantNode = None
@property
@ -214,6 +214,10 @@ class BaseNode:
def isConstantNode(self):
return False
@property
def isDuplicateNode(self):
return False
@property
def hasState(self):
"""False if the node is a pure functiom with no state

@ -144,6 +144,10 @@ class Duplicate2(GenericNode):
self.addOutput("oa",theType,inLength)
self.addOutput("ob",theType,inLength)
@property
def isDuplicateNode(self):
return True
@property
def typeName(self):
return "Duplicate2"
@ -157,6 +161,10 @@ class Duplicate3(GenericNode):
self.addOutput("ob",theType,inLength)
self.addOutput("oc",theType,inLength)
@property
def isDuplicateNode(self):
return True
@property
def typeName(self):
return "Duplicate3"

@ -1,5 +1,14 @@
{% macro io(node,theio) -%}
{% if node.isDuplicateNode %}
{{node.nodeName}}{% else %}
{% if not node.hasManyIOs %}{{node.nodeID}}:i{% else %}{{node.nodeID}}:{{theio.name}}{% endif %}
{% endif %}
{%- endmacro %}
{% macro edgelabel(ioport,name) -%}
{% if not ioport.owner.isDuplicateNode %}
,{{name}}=<<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{ioport.nbSamples}}</FONT>
</TD></TR></TABLE>>{% endif %}
{%- endmacro %}
{% macro constdst(theID) -%}
@ -29,6 +38,9 @@ digraph structs {
{% for item in nodes %}
{% if item.isDuplicateNode %}
{{item.nodeID}} [shape=point,label={{item.nodeName}}]
{% else %}
{% if not item.hasManyIOs %}
{{item.nodeID}} [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
@ -104,6 +116,7 @@ digraph structs {
</TABLE>>];
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
@ -111,33 +124,25 @@ digraph structs {
{{delayBox(id)}}
{% if fifos[id].hasDelay %}
{{io(fifos[id].src.owner,fifos[id].src)}} -> {{delayBoxID(id)}}:i [taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].src.nbSamples}}</FONT>
</TD></TR></TABLE>>]
{{io(fifos[id].src.owner,fifos[id].src)}} -> {{delayBoxID(id)}}:i [label=""{{edgelabel(fifos[id].src,"taillabel")}}]
{% if config.displayFIFOBuf %}
{{delayBoxID(id)}}:i -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].dst.nbSamples}}</FONT>
</TD></TR></TABLE>>,label="buf{{fifos[id].bufferID}}"]
{{delayBoxID(id)}}:i -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [label="buf{{fifos[id].bufferID}}"
{{edgelabel(fifos[id].src,"headlabel")}}]
{% else %}
{{delayBoxID(id)}}:i -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].dst.nbSamples}}</FONT>
</TD></TR></TABLE>>,label="{{fifos[id].theType.graphViztype}}({{fifos[id].length}})"]
{{delayBoxID(id)}}:i -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [label="{{fifos[id].theType.graphViztype}}({{fifos[id].length}})"
{{edgelabel(fifos[id].dst,"headlabel")}}]
{% endif %}
{% else %}
{% if config.displayFIFOBuf %}
{{io(fifos[id].src.owner,fifos[id].src)}} -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].dst.nbSamples}}</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].src.nbSamples}}</FONT>
</TD></TR></TABLE>>,label="buf{{fifos[id].bufferID}}"]
{{io(fifos[id].src.owner,fifos[id].src)}} -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [label="buf{{fifos[id].bufferID}}"
{{edgelabel(fifos[id].dst,"headlabel")}}
{{edgelabel(fifos[id].src,"taillabel")}}]
{% else %}
{{io(fifos[id].src.owner,fifos[id].src)}} -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [headlabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].dst.nbSamples}}</FONT>
</TD></TR></TABLE>>,taillabel=<
<TABLE BORDER="0" CELLPADDING="2"><TR><TD><FONT COLOR="blue" POINT-SIZE="12.0" >{{fifos[id].src.nbSamples}}</FONT>
</TD></TR></TABLE>>,label="{{fifos[id].theType.graphViztype}}({{fifos[id].length}})"]
{{io(fifos[id].src.owner,fifos[id].src)}} -> {{io(fifos[id].dst.owner,fifos[id].dst)}} [label="{{fifos[id].theType.graphViztype}}({{fifos[id].length}})"
{{edgelabel(fifos[id].dst,"headlabel")}}
{{edgelabel(fifos[id].src,"taillabel")}}]
{% endif %}
{% endif %}
{% endfor %}

Loading…
Cancel
Save