Skip to content

Commit 1012cf5

Browse files
authored
Merge pull request #189 from PSAL-POSTECH/tutorial
Tutorial
2 parents 8dc4705 + b225541 commit 1012cf5

148 files changed

Lines changed: 1109 additions & 1025 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Docker image for tutorial
2+
3+
on:
4+
push:
5+
branches: [ "tutorial" ]
6+
7+
jobs:
8+
build:
9+
runs-on: self-hosted
10+
11+
permissions:
12+
contents: read
13+
packages: write
14+
15+
steps:
16+
# Step 1: Checkout the repository
17+
- name: Checkout Code
18+
uses: actions/checkout@v4
19+
20+
# Step 2: Log in to GitHub Container Registry
21+
- name: Log in to GitHub Container Registry
22+
uses: docker/login-action@v3
23+
with:
24+
registry: ghcr.io
25+
username: ${{ github.actor }}
26+
password: ${{ secrets.GITHUB_TOKEN }}
27+
28+
# Step 3: Build and Push Docker Image
29+
- name: Build and Push Docker Image
30+
uses: docker/build-push-action@v4
31+
with:
32+
context: .
33+
file: ./Dockerfile.ksc2025
34+
push: true
35+
tags: ghcr.io/psal-postech/torchsim_ksc2025:latest

.github/workflows/pytorchsim_test.yml

Lines changed: 72 additions & 72 deletions
Large diffs are not rendered by default.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
__pycache__/
22
TOGSim/build/
33
.vscode
4+
*.txt
5+
*.ipynb_checkpoints
6+
output
7+
togsim_results/*
8+
outputs/*
9+
experiments/artifact/logs/*

PyTorchSimFrontend/extension_codecache.py

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def hash_prefix(hash_value):
1515
return hash_value[1:12]
1616

1717
def get_write_path(src_code):
18-
return os.path.join(extension_config.CONFIG_TORCHSIM_DUMP_PATH, "tmp", hash_prefix(get_hash(src_code.strip())))
18+
return os.path.join(extension_config.CONFIG_TORCHSIM_DUMP_PATH, "outputs", hash_prefix(get_hash(src_code.strip())))
1919

2020
def dump_metadata(args, arg_attributes, path):
2121
meta_path = os.path.join(path, "meta.txt")
@@ -27,19 +27,6 @@ def dump_metadata(args, arg_attributes, path):
2727
file.write(f'{arg_name}=({arg_attribute[0]}, {arg.dtype}, {arg.shape})\n')
2828
return
2929

30-
def llvm_compile_command(input, output):
31-
opt_output = f"{input[:-3]}_opt.ll"
32-
return [re.sub(r"[ \n]+", " ",
33-
f"""
34-
{extension_config.CONFIG_TORCHSIM_LLVM_PATH}/opt --load-pass-plugin={extension_config.CONFIG_TORCHSIM_CUSTOM_PASS_PATH}/libLowerGemminiPass.so -S -march=riscv64 --passes=LowerGemminiPass {input} -o {opt_output}
35-
""",
36-
).strip(),
37-
re.sub(r"[ \n]+", " ",
38-
f"""
39-
{extension_config.CONFIG_TORCHSIM_LLVM_PATH}/llc -march=riscv64 -mattr=+m,+f,+d,+a,+c,+v -O2 {opt_output} -o {output}
40-
""",
41-
).strip()]
42-
4330
def mlir_compile_command(filename, vectorlane_size, vlen=256):
4431
return [re.sub(r"[ \n]+", " ",
4532
f"""
@@ -165,7 +152,7 @@ def load(cls, source_code,
165152
else:
166153
link_option = ""
167154
# Generate LLVM kernel calller and binary for validation
168-
if extension_config.CONFIG_TORCHSIM_FUNCTIONAL_MODE:
155+
if extension_config.pytorchsim_functional_mode:
169156
# Use custom malloc to avoid size error
170157
new_link_option = link_option + " -Wl,--wrap=malloc -Wl,--wrap=free"
171158
cmds = mlir_compile_command(new_input_path, vectorlane_size, vlen=vlen)
@@ -182,7 +169,7 @@ def load(cls, source_code,
182169
print("Error output:", e.output)
183170
assert(0)
184171

185-
val_llvm_caller = MLIRKernelCallerCodeGen(extension_config.CONFIG_TORCHSIM_FUNCTIONAL_MODE, arg_attributes)
172+
val_llvm_caller = MLIRKernelCallerCodeGen(extension_config.pytorchsim_functional_mode, arg_attributes)
186173
val_llvm_caller.generate_wrapper_file(write_path, validation_wrapper_name)
187174
val_llvm_caller.compile_wih_kernel(write_path, key, validation_wrapper_name,
188175
validation_binary_name, new_link_option)
@@ -213,7 +200,7 @@ def load(cls, source_code,
213200
print("Error output:", e.output)
214201
assert(0)
215202

216-
if not extension_config.CONFIG_TORCHSIM_TIMING_MODE:
203+
if not extension_config.pytorchsim_timing_mode:
217204
return key
218205

219206
# Generate MLIR kernel calller and binary for cycle calculation
@@ -280,26 +267,26 @@ def dummy_simulator(*args, **kwargs):
280267
lock = FileLock(os.path.join(lock_dir, key + ".lock"), timeout=LOCK_TIMEOUT)
281268
with lock:
282269
# Run simulator pass
283-
result_path = os.path.join(extension_config.CONFIG_TORCHSIM_DUMP_PATH, "tmp", hash_prefix(key))
270+
result_path = os.path.join(extension_config.CONFIG_TORCHSIM_DUMP_PATH, "outputs", hash_prefix(key))
284271
# Dump arguments and meta data
285272
dump_metadata(args, arg_attributes, result_path)
286273
runtime_path = FunctionalSimulator.get_runtime_dump_path(result_path)
287-
if not autotune and (extension_config.CONFIG_TORCHSIM_FUNCTIONAL_MODE or validate):
274+
if not autotune and (extension_config.pytorchsim_functional_mode or validate):
288275
funcsim = FunctionalSimulator(result_path, key)
289276
funcsim.run_spike(args, arg_attributes,
290277
runtime_path, self.validation_binary_name,
291278
vectorlane_size=vectorlane_size, spad_info=spad_info,
292-
cleanup=extension_config.CONFIG_CLEANUP_DUMP_ARGS, silent_mode=silent_mode)
293-
if not extension_config.CONFIG_TORCHSIM_TIMING_MODE:
279+
silent_mode=silent_mode)
280+
if not extension_config.pytorchsim_timing_mode:
294281
return
295282

296283
onnx_path = os.path.join(result_path, "tile_graph.onnx")
297284
attribute_path = os.path.join(runtime_path, "attribute")
298285
togsim_path = os.path.join(extension_config.CONFIG_TORCHSIM_DIR, "TOGSim")
299-
backsim = TOGSimulator(togsim_path, extension_config.CONFIG_TOGSIM_CONFIG)
300-
backsim.vectorlane_size = vectorlane_size
301-
attribute_path = backsim.create_attribute_file(attribute_path, args, loop_size=loop_size)
302-
result_path = backsim.simulation(onnx_path, attribute_path, silent_mode=silent_mode)
286+
TOGSim = TOGSimulator(togsim_path, extension_config.CONFIG_TOGSIM_CONFIG)
287+
TOGSim.vectorlane_size = vectorlane_size
288+
attribute_path = TOGSim.create_attribute_file(attribute_path, args, loop_size=loop_size)
289+
result_path = TOGSim.simulation(onnx_path, attribute_path, silent_mode=silent_mode)
303290
result = TOGSimulator.get_result_from_file(result_path)
304291
return result
305292

@@ -310,23 +297,20 @@ def dryrun_simulator(*args, **kwargs):
310297
lock = FileLock(os.path.join(lock_dir, key + ".lock"), timeout=LOCK_TIMEOUT)
311298
with lock:
312299
# Run simulator pass
313-
result_path = os.path.join(extension_config.CONFIG_TORCHSIM_DUMP_PATH, "tmp", hash_prefix(key))
300+
result_path = os.path.join(extension_config.CONFIG_TORCHSIM_DUMP_PATH, "outputs", hash_prefix(key))
314301
# Dump arguments and meta data
315302
dump_metadata(args, arg_attributes, result_path)
316303
runtime_path = FunctionalSimulator.get_runtime_dump_path(result_path)
317-
if not extension_config.CONFIG_TORCHSIM_TIMING_MODE:
318-
return
319304

320305
# Todo. Support valude dependent mode for graph mode
321-
if False: # extension_config.CONFIG_TORCHSIM_FUNCTIONAL_MODE:
306+
if False: # extension_config.pytorchsim_functional_mode:
322307
funcsim = FunctionalSimulator(result_path, key)
323308
funcsim.run_spike(args, arg_attributes,
324309
runtime_path, self.validation_binary_name,
325-
vectorlane_size=vectorlane_size, spad_info=spad_info,
326-
cleanup=extension_config.CONFIG_CLEANUP_DUMP_ARGS)
310+
vectorlane_size=vectorlane_size, spad_info=spad_info)
327311
return result_path, runtime_path, None
328312

329-
is_dryrun = int(os.environ.get('TOGSIM_DRYRUN', default=False)) and not autotune
313+
is_dryrun = int(os.environ.get('TOGSIM_EAGER_MODE', default=False)) and not autotune
330314
target_simulator = dryrun_simulator if is_dryrun else dummy_simulator
331315
target_simulator.arg_attributes = arg_attributes
332316
target_simulator.future = future

PyTorchSimFrontend/extension_config.py

Lines changed: 63 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,89 @@
11
import os
22
import sys
3-
import tempfile
43
import importlib
4+
import json
5+
6+
CONFIG_TORCHSIM_DIR = os.environ.get('TORCHSIM_DIR', default='/workspace/PyTorchSim')
7+
CONFIG_GEM5_PATH = os.environ.get('GEM5_PATH', default="/workspace/gem5/build/RISCV/gem5.opt")
8+
CONFIG_TORCHSIM_LLVM_PATH = os.environ.get('TORCHSIM_LLVM_PATH', default="/usr/bin")
9+
10+
CONFIG_TORCHSIM_DUMP_MLIR_IR = int(os.environ.get("TORCHSIM_DUMP_MLIR_IR", default=False))
11+
CONFIG_TORCHSIM_DUMP_LLVM_IR = int(os.environ.get("TORCHSIM_DUMP_LLVM_IR", default=False))
512

613
def __getattr__(name):
14+
# TOGSim config
15+
config_path = os.environ.get('TOGSIM_CONFIG',
16+
default=f"{CONFIG_TORCHSIM_DIR}/configs/systolic_ws_128x128_c1_simple_noc_tpuv3.json")
17+
if name == "CONFIG_TOGSIM_CONFIG":
18+
return config_path
19+
config_json = json.load(open(config_path, 'r'))
720

821
# Hardware info config
9-
if name == "CONFIG_VECTOR_LANE":
10-
return int(os.environ.get("TORCHSIM_VECTOR_LANE", default=128))
11-
if name == "CONFIG_VECTOR_LANE_STRIDE":
12-
return int(os.environ.get("TORCHSIM_VECTOR_LANE_STRIDE", default=2))
22+
if name == "vpu_num_lanes":
23+
return config_json["vpu_num_lanes"]
1324
if name == "CONFIG_SPAD_INFO":
1425
return {
1526
"spad_vaddr" : 0xD0000000,
1627
"spad_paddr" : 0x2000000000,
17-
"spad_size" : int(os.environ.get("TORCHSIM_SPAD_SIZE", default=128)) << 10 # Note: spad size per lane
28+
"spad_size" : config_json["vpu_spad_size_kb_per_lane"] << 10 # Note: spad size per lane
1829
}
30+
1931
if name == "CONFIG_PRECISION":
20-
return 4 # 32bit
32+
return 4 # 32bit
2133
if name == "CONFIG_NUM_CORES":
22-
return 1
23-
if name == "CONFIG_VLEN":
24-
return 256 # 256bits / 32bits = 8 [elements]
25-
26-
# Tile size config
27-
if name == "CONFIG_TORCHSIM_DIR":
28-
return os.environ.get('TORCHSIM_DIR', default='/workspace/PyTorchSim')
29-
30-
if name == "CONFIG_TORCHSIM_DUMP_PATH":
31-
return os.environ.get('TORCHSIM_DUMP_PATH', default = f"{tempfile.gettempdir()}/torchinductor")
32-
if name == "CONFIG_TORCHSIM_DUMP_FILE":
33-
return int(os.environ.get('TORCHSIM_DUMP_FILE', default=True))
34-
if name == "CONFIG_TORCHSIM_FUNCTIONAL_MODE":
35-
return int(os.environ.get('TORCHSIM_FUNCTIONAL_MODE', default=True))
36-
if name == "CONFIG_TORCHSIM_TIMING_MODE":
37-
return int(os.environ.get("TORCHSIM_TIMING_MODE", True))
38-
if name == "CONFIG_CLEANUP_DUMP_ARGS":
39-
return int(os.environ.get('CLEANUP_DUMP_ARGS', default=False))
40-
41-
# LLVM PATH
42-
if name == "CONFIG_TORCHSIM_LLVM_PATH":
43-
return os.environ.get('TORCHSIM_LLVM_PATH', default="/usr/bin")
44-
if name == "CONFIG_TORCHSIM_CUSTOM_PASS_PATH":
45-
return os.environ.get('TORCHSIM_CUSTOM_PASS_PATH',
46-
default=f"{__getattr__('CONFIG_TORCHSIM_DIR')}/GemminiLowerPass/build")
47-
if name == "CONFIG_TORCHSIM_DUMP_MLIR_IR":
48-
return int(os.environ.get("TORCHSIM_DUMP_MLIR_IR", default=False))
49-
if name == "CONFIG_TORCHSIM_DUMP_LLVM_IR":
50-
return int(os.environ.get("TORCHSIM_DUMP_LLVM_IR", default=False))
51-
52-
# TOGSim config
53-
if name == "CONFIG_TOGSIM_CONFIG":
54-
return os.environ.get('TORCHSIM_CONFIG',
55-
default=f"{__getattr__('CONFIG_TORCHSIM_DIR')}/TOGSim/configs/systolic_ws_128x128_c1_simple_noc_tpuv3.json")
56-
if name == "CONFIG_TOGSIM_EAGER_MODE":
57-
return int(os.environ.get("TOGSIM_EAGER_MODE", default=False))
58-
if name == "CONFIG_TOGSIM_DRYRUN":
59-
return int(os.environ.get('TOGSIM_DRYRUN', default=False))
60-
if name == "CONFIG_TOGSIM_DEBUG_LEVEL":
61-
return os.environ.get("TOGSIM_DEBUG_LEVEL", "")
34+
return config_json["num_cores"]
35+
if name == "vpu_vector_length_bits":
36+
return config_json["vpu_vector_length_bits"]
37+
38+
if name == "pytorchsim_functional_mode":
39+
return config_json['pytorchsim_functional_mode']
40+
if name == "pytorchsim_timing_mode":
41+
return config_json['pytorchsim_timing_mode']
42+
43+
# Mapping strategy
44+
if name == "codegen_mapping_strategy":
45+
codegen_mapping_strategy = config_json["codegen_mapping_strategy"]
46+
assert(codegen_mapping_strategy in ["heuristic", "autotune", "external-then-heuristic", "external-then-autotune"]), "Invalid mapping strategy!"
47+
return codegen_mapping_strategy
48+
49+
if name == "codegen_external_mapping_file":
50+
return config_json["codegen_external_mapping_file"]
51+
52+
# Autotune config
53+
if name == "codegen_autotune_max_retry":
54+
return config_json["codegen_autotune_max_retry"]
55+
if name == "codegen_autotune_template_topk":
56+
return config_json["codegen_autotune_template_topk"]
6257

63-
# GEM5 config
64-
if name == "CONFIG_GEM5_PATH":
65-
return os.environ.get('GEM5_PATH', default="/workspace/gem5/build/RISCV/gem5.opt")
66-
if name == "CONFIG_GEM5_SCRIPT_PATH":
67-
return os.environ.get('GEM5_SCRIPT_PATH',
68-
default=f"{__getattr__('CONFIG_TORCHSIM_DIR')}/gem5_script/script_systolic.py")
69-
70-
# AUTOTUNE config
71-
if name == "CONFIG_AUTOTUNE":
72-
return int(os.environ.get('AUTOTUNE', default=False))
73-
if name == "CONFIG_AUTOTUNE_TEMPLATE":
74-
return int(os.environ.get('AUTOTUNE_TEMPLATE', default=False))
75-
if name == "CONFIG_MAX_AUTOTUNE_TRY":
76-
return int(os.environ.get('MAX_AUTOTUNE_TRY', default=10))
77-
if name == "CONFIG_AUTOTUNE_TEMPLATE_TOPK":
78-
return int(os.environ.get('AUTOTUNE_TEMPLATE_TOPK', default=4))
79-
80-
# For block sparse
81-
if name == "CONFIG_BLOCK_SPARSE":
82-
return int(os.environ.get('BLOCK_SPARSE', default=0))
83-
84-
# For GEMM tile size
85-
if name == "CONFIG_MANUAL_TILE_SIZE":
86-
return int(os.environ.get('TORCHSIM_MANUAL_TILE_SIZE', default=False))
87-
if name == "CONFIG_TILE_M":
88-
return int(os.getenv("TORCHSIM_TILE_M", __getattr__("CONFIG_VECTOR_LANE")))
89-
if name == "CONFIG_TILE_N":
90-
return int(os.getenv("TORCHSIM_TILE_N", __getattr__("CONFIG_VECTOR_LANE")))
91-
if name == "CONFIG_TILE_K":
92-
return int(os.getenv("TORCHSIM_TILE_K", __getattr__("CONFIG_VECTOR_LANE")))
93-
94-
if name == "CONFIG_SUBTILE":
95-
return int(os.environ.get('TORCHSIM_SUBTILE', default=True))
96-
if name == "CONFIG_MANUAL_SUBTILE_SIZE":
97-
return int(os.environ.get('TORCHSIM_MANUAL_SUBTILE_SIZE', default=False))
98-
if name == "CONFIG_SUBTILE_M":
99-
return int(os.environ.get('TORCHSIM_SUBTILE_M', default=__getattr__("CONFIG_VECTOR_LANE")))
100-
if name == "CONFIG_SUBTILE_N":
101-
return int(os.environ.get('TORCHSIM_SUBTILE_N', default=__getattr__("CONFIG_VECTOR_LANE")))
102-
if name == "CONFIG_SUBTILE_K":
103-
return int(os.environ.get('TORCHSIM_SUBTILE_K', default=__getattr__("CONFIG_VECTOR_LANE")))
104-
105-
if name == "CONFIG_GEMM_CHEATSHEET_PATH":
106-
return os.environ.get('TORCHSIM_GEMM_CHEATSHEET_PATH',
107-
default=f"{__getattr__('CONFIG_TORCHSIM_DIR')}/validation/gemm_tpuv3_cheatsheet.json")
10858
# Compiler Optimization
109-
if name == "CONFIG_COMPILER_OPTIMIZATION":
110-
return os.environ.get('TORCHSIM_COMPILER_OPTIMIZATION', default="all") # options: all, none, custom
59+
if name == "codegen_compiler_optimization":
60+
return config_json["codegen_compiler_optimization"]
61+
11162
# Advanced fusion options
11263
if name == "CONFIG_FUSION":
113-
return True if (__getattr__("CONFIG_COMPILER_OPTIMIZATION") == "all" or "fusion" in __getattr__("CONFIG_COMPILER_OPTIMIZATION")) else False
64+
return True if (__getattr__("codegen_compiler_optimization") == "all" or "fusion" in __getattr__("codegen_compiler_optimization")) else False
11465
if name == "CONFIG_FUSION_REDUCTION_EPILOGUE":
115-
return True if (__getattr__("CONFIG_COMPILER_OPTIMIZATION") == "all" or "reduction_epliogue" in __getattr__("CONFIG_COMPILER_OPTIMIZATION")) else False
66+
return True if (__getattr__("codegen_compiler_optimization") == "all" or "reduction_epliogue" in __getattr__("codegen_compiler_optimization")) else False
11667
if name == "CONFIG_FUSION_REDUCTION_REDUCTION":
117-
return True if (__getattr__("CONFIG_COMPILER_OPTIMIZATION") == "all" or "reduction_reduction" in __getattr__("CONFIG_COMPILER_OPTIMIZATION")) else False
68+
return True if (__getattr__("codegen_compiler_optimization") == "all" or "reduction_reduction" in __getattr__("codegen_compiler_optimization")) else False
11869
if name == "CONFIG_FUSION_PROLOGUE":
119-
return True if ((__getattr__("CONFIG_COMPILER_OPTIMIZATION") == "all") or ("prologue" in __getattr__("CONFIG_COMPILER_OPTIMIZATION"))) else False
70+
return True if ((__getattr__("codegen_compiler_optimization") == "all") or ("prologue" in __getattr__("codegen_compiler_optimization"))) else False
12071
if name == "CONFIG_SINGLE_BATCH_CONV":
121-
return True if (__getattr__("CONFIG_COMPILER_OPTIMIZATION") == "all" or "single_batch_conv" in __getattr__("CONFIG_COMPILER_OPTIMIZATION")) else False
72+
return True if (__getattr__("codegen_compiler_optimization") == "all" or "single_batch_conv" in __getattr__("codegen_compiler_optimization")) else False
12273
if name == "CONFIG_MULTI_TILE_CONV":
123-
return True if (__getattr__("CONFIG_COMPILER_OPTIMIZATION") == "all" or "multi_tile_conv" in __getattr__("CONFIG_COMPILER_OPTIMIZATION")) else False
74+
return True if (__getattr__("codegen_compiler_optimization") == "all" or "multi_tile_conv" in __getattr__("codegen_compiler_optimization")) else False
75+
if name == "CONFIG_SUBTILE":
76+
return True if (__getattr__("codegen_compiler_optimization") == "all" or "subtile" in __getattr__("codegen_compiler_optimization")) else False
77+
78+
if name == "CONFIG_TOGSIM_DEBUG_LEVEL":
79+
return os.environ.get("TOGSIM_DEBUG_LEVEL", "")
80+
if name == "CONFIG_TORCHSIM_DUMP_PATH":
81+
return os.environ.get('TORCHSIM_DUMP_PATH', default = CONFIG_TORCHSIM_DIR)
82+
if name == "CONFIG_TORCHSIM_LOG_PATH":
83+
return os.environ.get('TORCHSIM_DUMP_LOG_PATH', default = os.path.join(CONFIG_TORCHSIM_DIR, "togsim_results"))
84+
85+
if name == "CONFIG_TOGSIM_EAGER_MODE":
86+
return int(os.environ.get("TOGSIM_EAGER_MODE", default=False))
12487

12588
# SRAM Buffer allocation plan
12689
def load_plan_from_module(module_path):

PyTorchSimFrontend/extension_op.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
class MLIRExternKernelChoice(ExternKernelChoice):
4848
def call_name(self):
49-
is_dryrun = int(os.environ.get('TOGSIM_DRYRUN', default=False))
49+
is_dryrun = int(os.environ.get('TOGSIM_EAGER_MODE', default=False))
5050
if is_dryrun:
5151
return f"yield from sparse_mm_dummy_stonne_outer"
5252
return f"torch.ops.extension_op.{self.name}"
@@ -276,9 +276,9 @@ def sparse_mm_stonne_outer(a, b, out):
276276
onnx_path, attribute_path, c_result_path = prepare_outer_product_matrix(a, b, out)
277277

278278
togsim_path = os.path.join(extension_config.CONFIG_TORCHSIM_DIR, "TOGSim")
279-
stonne_config_path = f'{extension_config.CONFIG_TORCHSIM_DIR}/TOGSim/configs/stonne_single_c1_simple_noc.json'
280-
backsim = TOGSimulator(togsim_path, stonne_config_path)
281-
result_path = backsim.simulation(onnx_path)
279+
stonne_config_path = f'{extension_config.CONFIG_TORCHSIM_DIR}/configs/stonne_single_c1_simple_noc.json'
280+
TOGSim = TOGSimulator(togsim_path, stonne_config_path)
281+
result_path = TOGSim.simulation(onnx_path)
282282
TOGSimulator.get_result_from_file(result_path)
283283

284284
# Load result data

0 commit comments

Comments
 (0)