Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ACS
Public
VILLASframework
VILLASfpga
VILLASfpga
Commits
b509e870
Commit
b509e870
authored
Jun 04, 2018
by
Daniel Krebs
Browse files
ip-node: add implementation of StreamGraph for automatic routing
parent
b8dc8fd7
Changes
3
Hide whitespace changes
Inline
Side-by-side
include/villas/directed_graph.hpp
View file @
b509e870
...
...
@@ -29,6 +29,10 @@ class Vertex {
public:
using
Identifier
=
std
::
size_t
;
const
Identifier
&
getIdentifier
()
const
{
return
id
;
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
stream
,
const
Vertex
&
vertex
)
{
return
stream
<<
vertex
.
id
;
}
...
...
@@ -314,7 +318,7 @@ public:
}
}
pr
ivate
:
pr
otected
:
VertexIdentifier
lastVertexId
;
EdgeIdentifier
lastEdgeId
;
...
...
include/villas/fpga/ip_node.hpp
View file @
b509e870
...
...
@@ -43,6 +43,52 @@ namespace villas {
namespace
fpga
{
namespace
ip
{
class
StreamVertex
:
public
graph
::
Vertex
{
public:
StreamVertex
(
const
std
::
string
&
node
,
const
std
::
string
&
port
,
bool
isMaster
)
:
nodeName
(
node
),
portName
(
port
),
isMaster
(
isMaster
)
{}
std
::
string
getName
()
const
{
return
nodeName
+
"/"
+
portName
+
"("
+
(
isMaster
?
"M"
:
"S"
)
+
")"
;
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
stream
,
const
StreamVertex
&
vertex
)
{
return
stream
<<
vertex
.
getIdentifier
()
<<
": "
<<
vertex
.
getName
();
}
public:
std
::
string
nodeName
;
std
::
string
portName
;
bool
isMaster
;
};
class
StreamGraph
:
public
graph
::
DirectedGraph
<
StreamVertex
>
{
public:
StreamGraph
()
:
graph
::
DirectedGraph
<
StreamVertex
>
(
"StreamGraph"
)
{}
std
::
shared_ptr
<
StreamVertex
>
getOrCreateStreamVertex
(
const
std
::
string
&
node
,
const
std
::
string
&
port
,
bool
isMaster
)
{
for
(
auto
&
[
vertexId
,
vertex
]
:
vertices
)
{
(
void
)
vertexId
;
if
(
vertex
->
nodeName
==
node
and
vertex
->
portName
==
port
and
vertex
->
isMaster
==
isMaster
)
return
vertex
;
}
// vertex not found, create new one
auto
vertex
=
std
::
make_shared
<
StreamVertex
>
(
node
,
port
,
isMaster
);
addVertex
(
vertex
);
return
vertex
;
}
};
extern
StreamGraph
streamGraph
;
// TODO: reflect on interface that an IpNode exposes and how to design it to
// blend in with VILLASnode software nodes
class
IpNode
:
public
IpCore
{
...
...
@@ -58,6 +104,14 @@ public:
bool
connect
(
std
::
string
portName
,
const
StreamPort
&
to
);
bool
disconnect
(
std
::
string
portName
);
const
StreamVertex
&
getMasterPort
(
const
std
::
string
&
name
)
const
{
return
*
portsMaster
.
at
(
name
);
}
const
StreamVertex
&
getSlavePort
(
const
std
::
string
&
name
)
const
{
return
*
portsSlave
.
at
(
name
);
}
bool
loopbackPossible
()
const
;
bool
connectLoopback
();
...
...
@@ -65,8 +119,8 @@ private:
std
::
pair
<
std
::
string
,
std
::
string
>
getLoopbackPorts
()
const
;
protected:
std
::
map
<
std
::
string
,
StreamPort
>
portsMaster
;
std
::
map
<
std
::
string
,
StreamPort
>
portsSlave
;
std
::
map
<
std
::
string
,
std
::
shared_ptr
<
StreamVertex
>
>
portsMaster
;
std
::
map
<
std
::
string
,
std
::
shared_ptr
<
StreamVertex
>
>
portsSlave
;
};
class
IpNodeFactory
:
public
IpCoreFactory
{
...
...
lib/ip_node.cpp
View file @
b509e870
...
...
@@ -13,6 +13,8 @@ namespace fpga {
namespace
ip
{
StreamGraph
streamGraph
;
bool
IpNodeFactory
::
configureJson
(
IpCore
&
ip
,
json_t
*
json_ip
)
{
...
...
@@ -49,25 +51,28 @@ IpNodeFactory::configureJson(IpCore& ip, json_t* json_ip)
return
false
;
}
int
port_num
;
try
{
port_num
=
std
::
stoi
(
tokens
[
1
]);
}
catch
(
const
std
::
invalid_argument
&
)
{
logger
->
error
(
"Target port number is not an integer: '{}'"
,
target_raw
);
return
false
;
}
const
std
::
string
role
(
role_raw
);
const
bool
isMaster
=
(
role
==
"master"
or
role
==
"initiator"
);
IpNode
::
StreamPort
port
;
port
.
nodeName
=
tokens
[
0
];
port
.
portNumber
=
port_num
;
const
std
::
string
role
(
role_raw
);
if
(
role
==
"master"
or
role
==
"initiator"
)
{
ipNode
.
portsMaster
[
name_raw
]
=
port
;
auto
thisVertex
=
streamGraph
.
getOrCreateStreamVertex
(
ip
.
getInstanceName
(),
name_raw
,
isMaster
);
auto
connectedVertex
=
streamGraph
.
getOrCreateStreamVertex
(
tokens
[
0
],
tokens
[
1
],
not
isMaster
);
if
(
isMaster
)
{
streamGraph
.
addDefaultEdge
(
thisVertex
->
getIdentifier
(),
connectedVertex
->
getIdentifier
());
ipNode
.
portsMaster
[
name_raw
]
=
thisVertex
;
}
else
/* slave */
{
ipNode
.
portsSlave
[
name_raw
]
=
port
;
ipNode
.
portsSlave
[
name_raw
]
=
thisVertex
;
}
}
return
true
;
...
...
@@ -79,7 +84,7 @@ IpNode::getLoopbackPorts() const
for
(
auto
&
[
masterName
,
masterTo
]
:
portsMaster
)
{
for
(
auto
&
[
slaveName
,
slaveTo
]
:
portsSlave
)
{
// TODO: should we also check which IP both ports are connected to?
if
(
masterTo
.
nodeName
==
slaveTo
.
nodeName
)
{
if
(
masterTo
->
nodeName
==
slaveTo
->
nodeName
)
{
return
{
masterName
,
slaveName
};
}
}
...
...
@@ -105,11 +110,11 @@ IpNode::connectLoopback()
logger
->
debug
(
"master port: {}"
,
ports
.
first
);
logger
->
debug
(
"slave port: {}"
,
ports
.
second
);
logger
->
debug
(
"switch at: {}"
,
portMaster
.
nodeName
);
logger
->
debug
(
"switch at: {}"
,
portMaster
->
nodeName
);
// TODO: verify this is really a switch!
auto
axiStreamSwitch
=
reinterpret_cast
<
ip
::
AxiStreamSwitch
*>
(
card
->
lookupIp
(
portMaster
.
nodeName
));
card
->
lookupIp
(
portMaster
->
nodeName
));
if
(
axiStreamSwitch
==
nullptr
)
{
logger
->
error
(
"Cannot find switch"
);
...
...
@@ -117,7 +122,7 @@ IpNode::connectLoopback()
}
// switch's slave port is our master port and vice versa
return
axiStreamSwitch
->
connect
(
portMaster
.
portNumber
,
portSlave
.
portNumber
);
return
axiStreamSwitch
->
connect
(
*
portMaster
,
*
portSlave
);
}
}
// namespace ip
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment