-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
29 changed files
with
936 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,7 +36,7 @@ jobs: | |
ruff format --diff | ||
- name: Test with pytest | ||
run: | | ||
pytest test --cov exseos | ||
pytest test --cov exseos -m "not needs_vendor_tools" | ||
- name: Upload coverage reports to Codecov | ||
uses: codecov/[email protected] | ||
with: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# ExSeOS-H Hardware ML Workflow Manager | ||
# Copyright (C) 2024 Alexis Maya-Isabelle Shuping | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from exseos.types.Option import Some | ||
from exseos.types.Result import Okay, Fail | ||
from exseos.types.Variable import VariableSet, UnboundVariable | ||
from exseos.workflow.stage.Stage import Stage | ||
|
||
from keras import Model | ||
from hls4ml.model import ModelGraph | ||
from hls4ml.utils import config_from_keras_model | ||
from hls4ml.converters import convert_from_keras_model | ||
|
||
|
||
class ConvertKerasModel(Stage): | ||
input_vars = ( | ||
UnboundVariable("model", Model, "The model to convert."), | ||
UnboundVariable("granularity", str, default="model"), | ||
UnboundVariable("default_precision", str, default="fixed<16,6>"), | ||
UnboundVariable("default_reuse_factor", int, default=1), | ||
UnboundVariable("output_dir", str, default="my-hls-test"), | ||
UnboundVariable("project_name", "myproject"), | ||
UnboundVariable("input_data_tb", str | None, default=Some(None)), | ||
UnboundVariable("output_data_tb", str | None, default=Some(None)), | ||
UnboundVariable("backend", str, "HLS4ML backend to use", default="Vivado"), | ||
UnboundVariable("board", str | None, default=Some(None)), | ||
UnboundVariable("part", str | None, default=Some(None)), | ||
UnboundVariable("io_type", str, default="io_parallel"), | ||
UnboundVariable("hls_config", dict | None, default=None), | ||
) | ||
output_vars = ( | ||
UnboundVariable("hls_model", ModelGraph, "Converted model"), | ||
UnboundVariable("config", desc="Final HLS4ML-generated model configuration"), | ||
) | ||
|
||
async def run(self, inputs: VariableSet, _): | ||
stat = inputs.check_all() | ||
if stat.is_fail: | ||
return stat | ||
|
||
try: | ||
config = config_from_keras_model( | ||
inputs.model, | ||
inputs.granularity, | ||
inputs.backend, | ||
inputs.default_precision, | ||
inputs.default_reuse_factor, | ||
) | ||
|
||
hls_model = convert_from_keras_model( | ||
inputs.model, | ||
output_dir=inputs.output_dir, | ||
project_name=inputs.project_name, | ||
input_data_tb=inputs.input_data_tb, | ||
output_data_tb=inputs.output_data_tb, | ||
backend=inputs.backend, | ||
board=inputs.board, | ||
part=inputs.part, | ||
clock_period=inputs.clock_period, | ||
io_type=inputs.io_type, | ||
hls_config=inputs.hls_config, | ||
) | ||
|
||
return Okay( | ||
(self.output_vars[0].bind(hls_model), self.output_vars[1].bind(config)) | ||
) | ||
|
||
except Exception as e: | ||
return Fail([e]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# ExSeOS-H Hardware ML Workflow Manager | ||
# Copyright (C) 2024 Alexis Maya-Isabelle Shuping | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from exseos.types.Result import Okay, Fail | ||
from exseos.types.Variable import VariableSet, UnboundVariable | ||
from exseos.workflow.stage.Stage import Stage | ||
|
||
import numpy as np | ||
from hls4ml.model import ModelGraph | ||
from sklearn.metrics import accuracy_score | ||
|
||
|
||
class EvalModel(Stage): | ||
input_vars = ( | ||
UnboundVariable("model", ModelGraph, "The model to evaluate."), | ||
UnboundVariable("X", np.ndarray, "Test data for evaluation"), | ||
UnboundVariable("y", np.ndarray, "Labels for X"), | ||
) | ||
output_vars = ( | ||
UnboundVariable("accuracy", float, "HLS simulation model accuracy"), | ||
UnboundVariable( | ||
"predictions", | ||
np.ndarray, | ||
"Predictions generated by the HLS simulation model", | ||
), | ||
) | ||
|
||
async def run(self, inputs: VariableSet, _): | ||
stat = inputs.check_all() | ||
if stat.is_fail: | ||
return stat | ||
|
||
try: | ||
y_predictions = inputs.model.predict(np.ascontiguousarray(inputs.X)) | ||
|
||
accuracy = accuracy_score( | ||
np.argmax(inputs.y, axis=1), np.argmax(y_predictions, axis=1) | ||
) | ||
|
||
return Okay( | ||
( | ||
self.output_vars[0].bind(accuracy), | ||
self.output_vars[1].bind(y_predictions), | ||
) | ||
) | ||
except Exception as e: | ||
return Fail([e]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# ExSeOS-H Hardware ML Workflow Manager | ||
# Copyright (C) 2024 Alexis Maya-Isabelle Shuping | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from exseos.types.Result import Okay, Fail | ||
from exseos.types.Variable import VariableSet, UnboundVariable | ||
from exseos.workflow.stage.Stage import Stage | ||
|
||
from hls4ml.model import ModelGraph | ||
from hls4ml.report.vivado_report import parse_vivado_report | ||
|
||
|
||
class ParseVivadoReport(Stage): | ||
input_vars = ( | ||
UnboundVariable( | ||
"location", ModelGraph, "Location of the project to parse files for." | ||
), | ||
) | ||
output_vars = ( | ||
UnboundVariable("report", dict), | ||
UnboundVariable("LUT", int), | ||
UnboundVariable("FF", int), | ||
UnboundVariable("WorstLatency", int), | ||
) | ||
|
||
async def run(self, inputs: VariableSet, _): | ||
stat = inputs.check_all() | ||
if stat.is_fail: | ||
return stat | ||
|
||
try: | ||
report = parse_vivado_report(inputs.location) | ||
|
||
luts = report["CSynthesisReport"]["LUT"] | ||
ffs = report["CSynthesisReport"]["FF"] | ||
worst_latency = report["CSynthesisReport"]["WorstLatency"] | ||
|
||
return Okay( | ||
( | ||
self.output_vars[0].bind(report), | ||
self.output_vars[1].bind(luts), | ||
self.output_vars[2].bind(ffs), | ||
self.output_vars[3].bind(worst_latency), | ||
) | ||
) | ||
except Exception as e: | ||
return Fail([e]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# ExSeOS-H Hardware ML Workflow Manager | ||
# Copyright (C) 2024 Alexis Maya-Isabelle Shuping | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from exseos.types.Result import Okay, Fail | ||
from exseos.types.Variable import VariableSet, UnboundVariable | ||
from exseos.workflow.stage.Stage import Stage | ||
|
||
from hls4ml.model import ModelGraph | ||
|
||
|
||
class SynthModel(Stage): | ||
input_vars = ( | ||
UnboundVariable("model", ModelGraph, "The model to synthesize."), | ||
UnboundVariable( | ||
"backend_kwargs", dict, "Arguments for individual backends", default={} | ||
), | ||
) | ||
output_vars = () | ||
|
||
async def run(self, inputs: VariableSet, _): | ||
stat = inputs.check_all() | ||
if stat.is_fail: | ||
return stat | ||
|
||
try: | ||
inputs.model.build(**inputs.backend_kwargs) | ||
|
||
return Okay(()) | ||
except Exception as e: | ||
return Fail([e]) |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# ExSeOS-H Hardware ML Workflow Manager | ||
# Copyright (C) 2024 Alexis Maya-Isabelle Shuping | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from exseos.types.Result import Okay, Fail | ||
from exseos.types.Variable import VariableSet, UnboundVariable | ||
from exseos.workflow.stage.Stage import Stage | ||
|
||
import numpy as np | ||
from sklearn.preprocessing import LabelEncoder | ||
|
||
|
||
class ApplyLabelEncoder(Stage): | ||
input_vars = ( | ||
UnboundVariable("y", np.array, "The labels to encode."), | ||
UnboundVariable( | ||
"encoder_to_use", | ||
LabelEncoder, | ||
( | ||
"[Optional] A pre-trained encoder to use. If not provided, an " | ||
+ "encoder will be trained on the input data." | ||
), | ||
), | ||
) | ||
output_vars = ( | ||
UnboundVariable("y_encoded", np.array, "y encoded by encoder_to_use"), | ||
UnboundVariable( | ||
"trained_encoder", | ||
LabelEncoder, | ||
( | ||
"The trained encoder. If encoder_to_use was provided, then " | ||
+ "this will be the same as encoder_to_use; otherwise, it will " | ||
+ "be a new encoder trained on y." | ||
), | ||
), | ||
) | ||
|
||
async def run(self, inputs: VariableSet, _): | ||
stat = inputs.check("y") | ||
if stat.is_fail: | ||
return stat | ||
|
||
try: | ||
if inputs.check("encoder_to_use").is_fail: | ||
encoder: LabelEncoder = LabelEncoder() | ||
encoder.fit(inputs.y) | ||
else: | ||
encoder: LabelEncoder = inputs.scaler_to_use | ||
|
||
y_scaled = encoder.transform(inputs.y) | ||
|
||
return Okay( | ||
( | ||
self.output_vars[0].bind(y_scaled), | ||
self.output_vars[1].bind(encoder) | ||
) | ||
) | ||
except Exception as e: | ||
return Fail([e]) |
Oops, something went wrong.