Merge "Add xilinx fpga driver"
This commit is contained in:
commit
106f023573
0
cyborg/accelerator/drivers/fpga/xilinx/__init__.py
Normal file
0
cyborg/accelerator/drivers/fpga/xilinx/__init__.py
Normal file
74
cyborg/accelerator/drivers/fpga/xilinx/driver.py
Normal file
74
cyborg/accelerator/drivers/fpga/xilinx/driver.py
Normal file
@ -0,0 +1,74 @@
|
||||
# Copyright 2021 Inspur, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
"""
|
||||
Cyborg Xilinx FPGA driver implementation.
|
||||
"""
|
||||
from oslo_concurrency import processutils
|
||||
|
||||
from cyborg.accelerator.drivers.fpga.base import FPGADriver
|
||||
from cyborg.accelerator.drivers.fpga.xilinx import sysinfo
|
||||
from cyborg.common import exception
|
||||
import cyborg.privsep
|
||||
|
||||
|
||||
@cyborg.privsep.sys_admin_pctxt.entrypoint
|
||||
def _fpga_program_privileged(cmd_args):
|
||||
# Example: xbmgmt program --device 0000:d8:00.0
|
||||
# --base --image xilinx-u250-gen3x16-base
|
||||
cmd = ["/opt/xilinx/xrt/bin/xbmgmt"]
|
||||
cmd.extend(cmd_args)
|
||||
return processutils.execute(*cmd)
|
||||
|
||||
|
||||
class XilinxFPGADriver(FPGADriver):
|
||||
"""Class for Xilinx FPGA drivers.
|
||||
Vendor should implement their specific drivers in this class.
|
||||
"""
|
||||
VENDOR = "xilinx"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def discover(self):
|
||||
return sysinfo.fpga_tree()
|
||||
|
||||
def program(self, controlpath_id, image_file_path):
|
||||
"""Program the FPGA with the provided bitstream image.
|
||||
|
||||
:param controlpath_id: the ID of controlpath.
|
||||
:param image_file_path: the path of the image file
|
||||
:returns: True on success, False on failure
|
||||
"""
|
||||
if controlpath_id['cpid_type'] != "PCI":
|
||||
raise exception.InvalidType(obj='controlpath_id',
|
||||
type=controlpath_id['cpid_type'],
|
||||
expected='PCI')
|
||||
cmd_args = ['program']
|
||||
cmd_args.append('--device')
|
||||
bdf_dict = controlpath_id['cpid_info']
|
||||
# BDF format: domain:bus:device:function
|
||||
bdf = ':'.join([s for s in map(lambda x: bdf_dict[x],
|
||||
['domain', 'bus', 'device', 'function'])])
|
||||
cmd_args.append(bdf)
|
||||
cmd_args.append('--base')
|
||||
cmd_args.append('--image')
|
||||
cmd_args.append(image_file_path)
|
||||
|
||||
try:
|
||||
_fpga_program_privileged(cmd_args)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
188
cyborg/accelerator/drivers/fpga/xilinx/sysinfo.py
Normal file
188
cyborg/accelerator/drivers/fpga/xilinx/sysinfo.py
Normal file
@ -0,0 +1,188 @@
|
||||
# Copyright 2021 Inspur, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Cyborg Xilinx FPGA driver implementation.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from cyborg.accelerator.common import utils
|
||||
from cyborg.common import constants
|
||||
from cyborg.conf import CONF
|
||||
from cyborg.objects.driver_objects import driver_attach_handle
|
||||
from cyborg.objects.driver_objects import driver_attribute
|
||||
from cyborg.objects.driver_objects import driver_controlpath_id
|
||||
from cyborg.objects.driver_objects import driver_deployable
|
||||
from cyborg.objects.driver_objects import driver_device
|
||||
from cyborg.privsep import sys_admin_pctxt
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
XILINX_FPGA_FLAGS = ["Xilinx Corporation Device",
|
||||
"Processing accelerators"]
|
||||
|
||||
XILINX_FPGA_INFO_PATTERN = re.compile(
|
||||
r"(?P<pci_addr>[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:"
|
||||
r"[0-9a-fA-F]{2}\.[0-9a-fA-F]) "
|
||||
r"(?P<controller>.*) [\[].*]: (?P<model>.*) .*"
|
||||
r"[\[](?P<vendor_id>[0-9a-fA-F]"
|
||||
r"{4}):(?P<product_id>[0-9a-fA-F]{4})].*")
|
||||
|
||||
XILINX_PF_MAPS = {"mgmt": "xclmgmt", "user": "xocl"}
|
||||
|
||||
VENDOR_MAPS = {"10ee": "xilinx"}
|
||||
|
||||
|
||||
@sys_admin_pctxt.entrypoint
|
||||
def lspci_privileged(cmd):
|
||||
return processutils.execute(*cmd)
|
||||
|
||||
|
||||
def get_pci_devices(pci_flags, vendor_id=None):
|
||||
device_for_vendor_out = []
|
||||
all_device_out = []
|
||||
cmd = ['lspci', '-nnn', '-D']
|
||||
lspci_out = lspci_privileged(cmd)[0].split('\n')
|
||||
for i in range(len(lspci_out)):
|
||||
if all(x in lspci_out[i] for x in pci_flags):
|
||||
all_device_out.append(lspci_out[i])
|
||||
if vendor_id and vendor_id in lspci_out[i]:
|
||||
device_for_vendor_out.append(lspci_out[i])
|
||||
return device_for_vendor_out if vendor_id else all_device_out
|
||||
|
||||
|
||||
def _generate_traits(vendor_id, product_id):
|
||||
"""Generate traits for FPGAs.
|
||||
: param vendor_id: vendor_id of FPGA
|
||||
: param product_id: product_id of FPGA
|
||||
Example FPGA traits:
|
||||
{traits:["CUSTOM_FPGA_XILINX", "CUSTOM_FPGA_PRODUCT_ID_5001"]}
|
||||
"""
|
||||
traits = []
|
||||
traits.append("CUSTOM_FPGA_" + VENDOR_MAPS.get(vendor_id, "").upper())
|
||||
traits.append("CUSTOM_FPGA_PRODUCT_ID_" + product_id.upper())
|
||||
return {"traits": traits}
|
||||
|
||||
|
||||
def _get_pf_type(device):
|
||||
cmd = ['lspci', '-k', '-s', device]
|
||||
result = lspci_privileged(cmd)[0]
|
||||
for k, v in XILINX_PF_MAPS.items():
|
||||
if v in result:
|
||||
return k
|
||||
|
||||
|
||||
def _combine_device_by_pci_func(pci_devices):
|
||||
fpga_devices = []
|
||||
for pci_dev in pci_devices:
|
||||
m = XILINX_FPGA_INFO_PATTERN.match(pci_dev)
|
||||
if m:
|
||||
pci_dict = m.groupdict()
|
||||
LOG.debug('Xilinx fpga pci device in dict: %s', pci_dict)
|
||||
# 0000:3b:00.0/1
|
||||
is_existed = False
|
||||
new_addr = pci_dict.get('pci_addr')
|
||||
for fpga in fpga_devices:
|
||||
existed_addr = fpga.get('pci_addr')[0]
|
||||
# compare domain:bus:slot
|
||||
if existed_addr and \
|
||||
new_addr.split('.')[0] == existed_addr.split('.')[0]:
|
||||
fpga.update({'pci_addr': [existed_addr, new_addr]})
|
||||
is_existed = True
|
||||
if not is_existed:
|
||||
traits = _generate_traits(pci_dict["vendor_id"],
|
||||
pci_dict["product_id"])
|
||||
pci_dict["rc"] = constants.RESOURCES["FPGA"]
|
||||
pci_dict.update(traits)
|
||||
pci_dict.update({'pci_addr': [new_addr]})
|
||||
fpga_devices.append(pci_dict)
|
||||
return fpga_devices
|
||||
|
||||
|
||||
def _generate_controlpath_id(fpga):
|
||||
driver_cpid = driver_controlpath_id.DriverControlPathID()
|
||||
driver_cpid.cpid_type = "PCI"
|
||||
driver_cpid.cpid_info = utils.pci_str_to_json(fpga['pci_addr'][0])
|
||||
return driver_cpid
|
||||
|
||||
|
||||
def _generate_dep_list(fpga):
|
||||
dep_list = []
|
||||
driver_dep = driver_deployable.DriverDeployable()
|
||||
driver_dep.attribute_list = _generate_attribute_list(fpga)
|
||||
driver_dep.attach_handle_list = []
|
||||
driver_dep.name = CONF.host + '_' + fpga["pci_addr"][0]
|
||||
driver_dep.driver_name = VENDOR_MAPS.get(fpga["vendor_id"]).upper()
|
||||
driver_dep.num_accelerators = 1
|
||||
driver_dep.attach_handle_list = _generate_attach_handle(fpga)
|
||||
dep_list.append(driver_dep)
|
||||
return dep_list
|
||||
|
||||
|
||||
def _generate_attribute_list(fpga):
|
||||
attr_list = []
|
||||
for k, v in fpga.items():
|
||||
if k == "rc":
|
||||
driver_attr = driver_attribute.DriverAttribute()
|
||||
driver_attr.key, driver_attr.value = k, v
|
||||
attr_list.append(driver_attr)
|
||||
if k == "traits":
|
||||
values = fpga.get(k, [])
|
||||
for index, val in enumerate(values):
|
||||
driver_attr = driver_attribute.DriverAttribute(
|
||||
key="trait" + str(index), value=val)
|
||||
attr_list.append(driver_attr)
|
||||
return attr_list
|
||||
|
||||
|
||||
def _generate_attach_handle(fpga):
|
||||
driver_ahs = []
|
||||
for addr in fpga.get('pci_addr'):
|
||||
driver_ah = driver_attach_handle.DriverAttachHandle()
|
||||
driver_ah.attach_type = constants.AH_TYPE_PCI
|
||||
driver_ah.attach_info = utils.pci_str_to_json(addr)
|
||||
driver_ah.in_use = False
|
||||
driver_ahs.append(driver_ah)
|
||||
return driver_ahs
|
||||
|
||||
|
||||
def fpga_tree():
|
||||
fpga_list = []
|
||||
fpga_pci_devices = get_pci_devices(XILINX_FPGA_FLAGS)
|
||||
LOG.debug("Xilinx fpga devices from lspci: %s", fpga_pci_devices)
|
||||
# In the return pci devices, mgmt pf and user pf are two entries.
|
||||
# Now only when binding both to vm, end user can program it.
|
||||
# So combine these two entries into one device.
|
||||
for fpga in _combine_device_by_pci_func(fpga_pci_devices):
|
||||
driver_device_obj = driver_device.DriverDevice()
|
||||
driver_device_obj.vendor = fpga["vendor_id"]
|
||||
driver_device_obj.model = fpga.get('model', 'miss model info')
|
||||
std_board_info = {'product_id': fpga.get('product_id', None),
|
||||
'controller': fpga.get('controller', None)}
|
||||
vendor_board_info = {
|
||||
'vendor_info': fpga.get('vendor_info', 'fpga_vb_info')}
|
||||
driver_device_obj.std_board_info = jsonutils.dumps(std_board_info)
|
||||
driver_device_obj.vendor_board_info = \
|
||||
jsonutils.dumps(vendor_board_info)
|
||||
driver_device_obj.type = constants.DEVICE_FPGA
|
||||
driver_device_obj.stub = fpga.get('stub', False)
|
||||
driver_device_obj.controlpath_id = _generate_controlpath_id(fpga)
|
||||
driver_device_obj.deployable_list = _generate_dep_list(fpga)
|
||||
fpga_list.append(driver_device_obj)
|
||||
return fpga_list
|
@ -135,9 +135,18 @@ class ARQsController(base.CyborgController):
|
||||
|
||||
extarq_list = []
|
||||
for group_id, group in enumerate(devprof.groups):
|
||||
accel_resources = [
|
||||
int(val) for key, val in group.items()
|
||||
if key.startswith('resources')]
|
||||
accel_resources = []
|
||||
# If the device profile requires the Xilinx fpga, the number of
|
||||
# resources should multiply by 2 cause that end user can program
|
||||
# the device only when both MGMT and USER PF are bound to
|
||||
# instance.
|
||||
if group.get("trait:CUSTOM_FPGA_XILINX") == "required":
|
||||
accel_resources = [int(group.get("resources:FPGA"))] * 2
|
||||
else:
|
||||
accel_resources = [
|
||||
int(val) for key, val in group.items()
|
||||
if key.startswith('resources')]
|
||||
|
||||
# If/when we introduce non-accelerator resources, like
|
||||
# device-local memory, the key search above needs to be
|
||||
# made specific to accelerator resources only.
|
||||
|
@ -15,6 +15,7 @@
|
||||
from cyborg.accelerator.drivers.fpga.base import FPGADriver
|
||||
from cyborg.accelerator.drivers.fpga.intel.driver import IntelFPGADriver # noqa
|
||||
from cyborg.accelerator.drivers.fpga.inspur.driver import InspurFPGADriver # noqa
|
||||
from cyborg.accelerator.drivers.fpga.xilinx.driver import XilinxFPGADriver # noqa
|
||||
from cyborg.tests import base
|
||||
|
||||
|
||||
@ -22,7 +23,8 @@ class TestFPGADriver(base.TestCase):
|
||||
def test_create(self):
|
||||
FPGADriver.create("intel")
|
||||
FPGADriver.create("inspur")
|
||||
self.assertRaises(LookupError, FPGADriver.create, "xilinx")
|
||||
FPGADriver.create("xilinx")
|
||||
self.assertRaises(LookupError, FPGADriver.create, "fake")
|
||||
|
||||
def test_discover(self):
|
||||
d = FPGADriver()
|
||||
|
129
cyborg/tests/unit/accelerator/drivers/fpga/xilinx/test_driver.py
Normal file
129
cyborg/tests/unit/accelerator/drivers/fpga/xilinx/test_driver.py
Normal file
@ -0,0 +1,129 @@
|
||||
# Copyright 2021 Inspur, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from unittest import mock
|
||||
|
||||
from cyborg.accelerator.drivers.fpga.xilinx.driver import XilinxFPGADriver
|
||||
from cyborg.tests import base
|
||||
|
||||
XILINX_FPGA_INFO = ["0000:3b:00.0 Processing accelerators [1200]: "
|
||||
"Xilinx Corporation Device [10ee:5000]\n"
|
||||
"0000:3b:00.1 Processing accelerators [1200]: "
|
||||
"Xilinx Corporation Device [10ee:5001]"]
|
||||
|
||||
|
||||
def fake_output(arg):
|
||||
if arg == ['lspci', '-nnn', '-D']:
|
||||
return XILINX_FPGA_INFO
|
||||
|
||||
|
||||
class TestXilinxFPGADriver(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestXilinxFPGADriver, self).setUp()
|
||||
|
||||
@mock.patch('cyborg.accelerator.drivers.fpga.'
|
||||
'xilinx.sysinfo.lspci_privileged')
|
||||
def test_discover(self, mock_devices_for_vendor):
|
||||
mock_devices_for_vendor.side_effect = fake_output
|
||||
self.set_defaults(host='fake-host', debug=True)
|
||||
fpga_list = XilinxFPGADriver().discover()
|
||||
self.assertEqual(1, len(fpga_list))
|
||||
attach_handle_list = [
|
||||
{'attach_type': 'PCI',
|
||||
'attach_info': '{"bus": "3b", '
|
||||
'"device": "00", '
|
||||
'"domain": "0000", '
|
||||
'"function": "0"}',
|
||||
'in_use': False},
|
||||
{'attach_type': 'PCI',
|
||||
'attach_info': '{"bus": "3b", '
|
||||
'"device": "00", '
|
||||
'"domain": "0000", '
|
||||
'"function": "1"}',
|
||||
'in_use': False}
|
||||
]
|
||||
attribute_list = [
|
||||
{'key': 'rc', 'value': 'FPGA'},
|
||||
{'key': 'trait0', 'value': 'CUSTOM_FPGA_XILINX'},
|
||||
{'key': 'trait1', 'value': 'CUSTOM_FPGA_PRODUCT_ID_5000'},
|
||||
]
|
||||
expected = {
|
||||
'vendor': '10ee',
|
||||
'type': 'FPGA',
|
||||
'std_board_info': {"controller": "Processing accelerators",
|
||||
"product_id": "5000"},
|
||||
'vendor_board_info': {"vendor_info": "fpga_vb_info"},
|
||||
'deployable_list':
|
||||
[
|
||||
{
|
||||
'num_accelerators': 1,
|
||||
'driver_name': 'XILINX',
|
||||
'name': 'fake-host_0000:3b:00.0',
|
||||
'attach_handle_list': attach_handle_list,
|
||||
'attribute_list': attribute_list
|
||||
},
|
||||
],
|
||||
'controlpath_id': {'cpid_info': '{"bus": "3b", '
|
||||
'"device": "00", '
|
||||
'"domain": "0000", '
|
||||
'"function": "0"}',
|
||||
'cpid_type': 'PCI'}
|
||||
}
|
||||
fpga_obj = fpga_list[0]
|
||||
fpga_dict = fpga_obj.as_dict()
|
||||
fpga_dep_list = fpga_dict['deployable_list']
|
||||
fpga_attach_handle_list = (
|
||||
fpga_dep_list[0].as_dict()['attach_handle_list'])
|
||||
fpga_attribute_list = fpga_dep_list[0].as_dict()['attribute_list']
|
||||
attri_obj_data = []
|
||||
[attri_obj_data.append(attr.as_dict()) for attr in fpga_attribute_list]
|
||||
attribute_actual_data = sorted(attri_obj_data, key=lambda i: i['key'])
|
||||
self.assertEqual(expected['vendor'], fpga_dict['vendor'])
|
||||
self.assertEqual(expected['controlpath_id'],
|
||||
fpga_dict['controlpath_id'])
|
||||
self.assertEqual(expected['std_board_info'],
|
||||
jsonutils.loads(fpga_dict['std_board_info']))
|
||||
self.assertEqual(expected['vendor_board_info'],
|
||||
jsonutils.loads(fpga_dict['vendor_board_info']))
|
||||
self.assertEqual(expected['deployable_list'][0]['num_accelerators'],
|
||||
fpga_dep_list[0].as_dict()['num_accelerators'])
|
||||
self.assertEqual(expected['deployable_list'][0]['name'],
|
||||
fpga_dep_list[0].as_dict()['name'])
|
||||
self.assertEqual(expected['deployable_list'][0]['driver_name'],
|
||||
fpga_dep_list[0].as_dict()['driver_name'])
|
||||
self.assertEqual(2, len(fpga_attach_handle_list))
|
||||
self.assertEqual(attach_handle_list[0],
|
||||
fpga_attach_handle_list[0].as_dict())
|
||||
self.assertEqual(attach_handle_list[1],
|
||||
fpga_attach_handle_list[1].as_dict())
|
||||
self.assertEqual(attribute_list, attribute_actual_data)
|
||||
|
||||
@mock.patch('cyborg.accelerator.drivers.fpga.xilinx.driver.'
|
||||
'_fpga_program_privileged')
|
||||
def test_program(self, mock_prog):
|
||||
bdf = '0000:3b:00:0'
|
||||
expect_cmd_args = ['program', '--device', bdf, '--base',
|
||||
'--image', '/path/image']
|
||||
|
||||
xilinx_driver = XilinxFPGADriver()
|
||||
cpid_info = {"domain": "0000", "bus": "3b",
|
||||
"device": "00", "function": "0"}
|
||||
cpid = {'cpid_type': 'PCI', 'cpid_info': cpid_info}
|
||||
|
||||
# program PF
|
||||
mock_prog.return_value = bytes([0])
|
||||
xilinx_driver.program(cpid, "/path/image")
|
||||
mock_prog.assert_called_with(expect_cmd_args)
|
@ -203,6 +203,26 @@ class TestARQsController(v2_test.APITestV2):
|
||||
dp_group_id = idx
|
||||
self.assertEqual(dp_group_id, out_arq['device_profile_group_id'])
|
||||
|
||||
@mock.patch('cyborg.objects.DeviceProfile.get_by_name')
|
||||
@mock.patch('cyborg.conductor.rpcapi.ConductorAPI.arq_create')
|
||||
def test_create_with_xilinx_fpga(self, mock_obj_extarq, mock_obj_dp):
|
||||
xilinx_fpga_dp = fake_device_profile.get_xilinx_fpga_devprof()
|
||||
mock_obj_dp.return_value = dp = xilinx_fpga_dp
|
||||
fake_xilinx_fpga_objs = fake_extarq.get_fake_xilinx_fpga_extarq_objs()
|
||||
mock_obj_extarq.side_effect = fake_xilinx_fpga_objs
|
||||
params = {'device_profile_name': dp['name']}
|
||||
response = self.post_json(self.ARQ_URL, params, headers=self.headers)
|
||||
data = jsonutils.loads(response.__dict__['controller_output'])
|
||||
out_arqs = data['arqs']
|
||||
|
||||
self.assertEqual(HTTPStatus.CREATED, response.status_int)
|
||||
self.assertEqual(len(out_arqs), 2)
|
||||
for in_extarq, out_arq in zip(fake_xilinx_fpga_objs, out_arqs):
|
||||
self._validate_arq(in_extarq.arq, out_arq)
|
||||
for idx, out_arq in enumerate(out_arqs):
|
||||
dp_group_id = idx
|
||||
self.assertEqual(dp_group_id, out_arq['device_profile_group_id'])
|
||||
|
||||
@mock.patch('cyborg.objects.DeviceProfile.get_by_name')
|
||||
@mock.patch('cyborg.objects.ExtARQ.create')
|
||||
def test_create_with_wrong_dp(self, mock_obj_extarq, mock_obj_dp):
|
||||
|
@ -106,3 +106,23 @@ def get_db_devprofs():
|
||||
dp_list = _get_device_profiles_as_dict()
|
||||
db_devprofs = list(map(_convert_to_db_devprof, dp_list))
|
||||
return db_devprofs
|
||||
|
||||
|
||||
def get_xilinx_fpga_devprof():
|
||||
xilinx_fpga_dp = {
|
||||
"id": 3,
|
||||
"uuid": "638828d7-7145-4060-904c-894aa726b133",
|
||||
"name": 'fake_xilinx_fpga_dp',
|
||||
"description": "fake_xilinx_fpga_dp-desc",
|
||||
"created_at": datetime.datetime(
|
||||
2022, 1, 22, 10, 40, 56,
|
||||
tzinfo=datetime.timezone.utc),
|
||||
"updated_at": None,
|
||||
"groups": [
|
||||
{"resources:FPGA": "1",
|
||||
"trait:CUSTOM_FPGA_XILINX": "required",
|
||||
"trait:CUSTOM_FPGA_PRODUCT_ID_5000": "required",
|
||||
},
|
||||
]
|
||||
}
|
||||
return _convert_to_obj(xilinx_fpga_dp)
|
||||
|
@ -300,3 +300,47 @@ def get_patch_list(same_device=True):
|
||||
'value': dev_uuid}
|
||||
patch_list[newarq['uuid']] = [host_binding, inst_binding, dev_binding]
|
||||
return patch_list, device_rp_uuid
|
||||
|
||||
|
||||
def get_fake_xilinx_fpga_extarq_objs():
|
||||
arqs = [
|
||||
{"uuid": 'b8c19eb2-e03c-47b4-b7cf-ced6086b2d11',
|
||||
"device_profile_group_id": 0,
|
||||
"state": "Initial",
|
||||
"device_profile_name": "fake_xilinx_fpga_dp",
|
||||
"hostname": "myhost",
|
||||
"instance_uuid": "5922a70f-1e06-4cfd-88dd-a332120d7144",
|
||||
"attach_handle_type": "PCI",
|
||||
# attach_handle info should vary across ARQs but ignored for testing
|
||||
"attach_handle_info": {
|
||||
"bus": "3b",
|
||||
"device": "00",
|
||||
"domain": "0000",
|
||||
"function": "0"
|
||||
},
|
||||
"device_profile_group": {
|
||||
"trait:CUSTOM_FPGA_XILINX": "required",
|
||||
"resources:FPGA": "1",
|
||||
"trait:CUSTOM_FPGA_PRODUCT_ID_5000": "required"}
|
||||
},
|
||||
{"uuid": '012955c7-90f9-45a9-bb7d-7c2907d8997f',
|
||||
"device_profile_group_id": 1,
|
||||
"state": "Initial",
|
||||
"device_profile_name": "fake_xilinx_fpga_dp",
|
||||
"hostname": "myhost",
|
||||
"instance_uuid": "5922a70f-1e06-4cfd-88dd-a332120d7144",
|
||||
"attach_handle_type": "PCI",
|
||||
# attach_handle info should vary across ARQs but ignored for testing
|
||||
"attach_handle_info": {
|
||||
"bus": "3b",
|
||||
"device": "00",
|
||||
"domain": "0000",
|
||||
"function": "1"
|
||||
},
|
||||
"device_profile_group": {
|
||||
"trait:CUSTOM_FPGA_XILINX": "required",
|
||||
"resources:FPGA": "1",
|
||||
"trait:CUSTOM_FPGA_PRODUCT_ID_5000": "required"}
|
||||
},
|
||||
]
|
||||
return list(map(_convert_from_dict_to_obj, arqs))
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add the Xilinx FPGA driver. Through this driver Cyborg can manage Xilinx
|
||||
FPGA devices, including discovering devices' info and programming
|
||||
``xclbin``.
|
@ -47,6 +47,7 @@ cyborg.database.migration_backend =
|
||||
cyborg.accelerator.driver =
|
||||
intel_fpga_driver = cyborg.accelerator.drivers.fpga.intel.driver:IntelFPGADriver
|
||||
inspur_fpga_driver = cyborg.accelerator.drivers.fpga.inspur.driver:InspurFPGADriver
|
||||
xilinx_fpga_driver = cyborg.accelerator.drivers.fpga.xilinx.driver:XilinxFPGADriver
|
||||
nvmf_spdk_driver = cyborg.accelerator.drivers.spdk.nvmf.nvmf:NVMFDRIVER
|
||||
nvidia_gpu_driver = cyborg.accelerator.drivers.gpu.nvidia.driver:NVIDIAGPUDriver
|
||||
fake_driver = cyborg.accelerator.drivers.fake:FakeDriver
|
||||
|
Loading…
Reference in New Issue
Block a user