Skip to content

Commit f3d6451

Browse files
authored
Fix bug with None dart_command during interactive debug with no timeout (#49)
1 parent 8f605a9 commit f3d6451

File tree

9 files changed

+123
-51
lines changed

9 files changed

+123
-51
lines changed

.github/workflows/general.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ jobs:
3333

3434
- name: Setup Dart
3535
uses: dart-lang/setup-dart@v1
36+
with:
37+
sdk: 3.6.2 # downgrade pending https://github.com/dart-lang/dartdoc/issues/3996
3638

3739
- name: Install Dart dependencies
3840
run: tool/gh_actions/install_dart_dependencies.sh
@@ -90,6 +92,8 @@ jobs:
9092

9193
- name: Setup Dart
9294
uses: dart-lang/setup-dart@v1
95+
with:
96+
sdk: 3.6.2 # downgrade pending https://github.com/dart-lang/dartdoc/issues/3996
9397

9498
- name: Install dart dependencies
9599
run: tool/gh_actions/install_dart_dependencies.sh

analysis_options.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ linter:
118118
- one_member_abstracts
119119
- only_throw_errors
120120
- overridden_fields
121-
- package_api_docs
121+
# - package_api_docs
122122
- package_names
123123
- package_prefixed_library_names
124124
- parameter_assignments
@@ -206,7 +206,7 @@ linter:
206206
- unnecessary_to_list_in_spreads
207207
# - unreachable_from_main
208208
- unrelated_type_equality_checks
209-
- unsafe_html
209+
# - unsafe_html
210210
- use_build_context_synchronously
211211
- use_colored_box
212212
- use_decorated_box

lib/src/configs/cosim_config.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2022-2023 Intel Corporation
1+
// Copyright (C) 2022-2025 Intel Corporation
22
// SPDX-License-Identifier: BSD-3-Clause
33
//
44
// cosim_config.dart
@@ -28,6 +28,20 @@ class CosimConnection {
2828
///
2929
/// Will run [disconnect] when the cosimulation is over.
3030
CosimConnection(this.socket, {this.disconnect = _defaultDisconnect});
31+
32+
/// A regular expression for usage in [extractSocketPort].
33+
static final _cosimSocketRegex = RegExp(r'ROHD COSIM SOCKET:(\d+)');
34+
35+
/// Extracts a socket number from a stdout [message] from the cosimulation
36+
/// process. Returns `null` if no socket number is found in [message].
37+
static int? extractSocketPort(String message) {
38+
final match = _cosimSocketRegex.firstMatch(message);
39+
if (match != null) {
40+
return int.parse(match.group(1)!);
41+
}
42+
43+
return null;
44+
}
3145
}
3246

3347
/// Configuration information for cosimulation.

lib/src/configs/cosim_process_config.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2022-2023 Intel Corporation
1+
// Copyright (C) 2022-2025 Intel Corporation
22
// SPDX-License-Identifier: BSD-3-Clause
33
//
44
// cosim_process_config.dart
@@ -85,17 +85,14 @@ abstract class CosimProcessConfig extends CosimConfig {
8585
}
8686

8787
unawaited(procFuture.then((proc) {
88-
final cosimSocketRegex = RegExp(r'ROHD COSIM SOCKET:(\d+)');
89-
9088
proc.stdout.transform(utf8.decoder).forEach((msg) async {
9189
Cosim.logger?.finest('SIM STDOUT:\n$msg');
9290
cosimLog(msg);
9391

9492
if (!socketConnectionCompleter.isCompleted) {
95-
// look for a string indicating the socket to connect to
96-
final match = cosimSocketRegex.firstMatch(msg);
97-
if (match != null) {
98-
final socketNumber = int.parse(match.group(1)!);
93+
final socketNumber = CosimConnection.extractSocketPort(msg);
94+
95+
if (socketNumber != null) {
9996
socket = await Socket.connect(
10097
InternetAddress.loopbackIPv4, socketNumber);
10198
socketConnectionCompleter.complete();

python/rohd_connector.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (C) 2022-2024 Intel Corporation
2+
Copyright (C) 2022-2025 Intel Corporation
33
SPDX-License-Identifier: BSD-3-Clause
44
55
rohd_connector.py
@@ -169,8 +169,11 @@ async def listen_for_stimulus(self, name_to_signal_map):
169169

170170
if (
171171
self.last_message_received_time is not None
172-
and (time.time() - self.last_message_received_time)
173-
> self.dart_connect_timeout
172+
and self.dart_connect_timeout is not None
173+
and (
174+
(time.time() - self.last_message_received_time)
175+
> self.dart_connect_timeout
176+
)
174177
):
175178
self._error(
176179
"Timeout waiting for Dart messages! Perhaps the Dart side has hung "

python/rohd_port_connector.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,10 @@ def run_dart_thread() -> subprocess.Popen:
159159
await cosim_test_module.setup_connections(dut, connector)
160160

161161
except Exception as exception:
162-
traceback.print_exc()
163-
fail_msg = f"ERROR: Exception encountered during cosim: {exception}"
162+
full_traceback = traceback.format_exc()
163+
fail_msg = (
164+
f"ERROR: Exception encountered during cosim: {exception}\n{full_traceback}"
165+
)
164166
print(fail_msg, flush=True)
165167
connector.shutdown()
166168
print("ERROR: Test failed due to exception.")

test/port_stuff/custom_test_module.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (C) 2022 Intel Corporation
2+
Copyright (C) 2022-2025 Intel Corporation
33
SPDX-License-Identifier: BSD-3-Clause
44
55
custom_test.py
@@ -27,6 +27,8 @@
2727
dart_fail = os.getenv('DART_FAIL')
2828
dart_fail_async = os.getenv('DART_FAIL_ASYNC')
2929
dart_hang = os.getenv('DART_HANG')
30+
separate_dart_launch = os.getenv('SEPARATE_DART_LAUNCH')
31+
python_fail = os.getenv('PYTHON_FAIL')
3032

3133
@cocotb.test()
3234
async def custom_test(dut):
@@ -52,9 +54,11 @@ def dart_command(port):
5254
await rohd_port_connector.launch_on_port(
5355
cosim_test_module=cosim_test_module,
5456
dut=dut,
55-
# dart_command= None,
56-
dart_command = dart_command,
57+
dart_command = dart_command if not separate_dart_launch else None,
5758
log_name='custom_test',
5859
enable_logging=False,
59-
dart_connect_timeout=5,
60+
dart_connect_timeout = 5 if not separate_dart_launch else None,
6061
)
62+
63+
if python_fail:
64+
raise Exception("Python test failure injected")

test/port_stuff/port_launch.dart

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2022-2023 Intel Corporation
1+
// Copyright (C) 2022-2025 Intel Corporation
22
// SPDX-License-Identifier: BSD-3-Clause
33
//
44
// port_launch.dart
@@ -7,16 +7,14 @@
77
// 2022 October 27
88
// Author: Max Korbel <[email protected]>
99

10-
// ignore_for_file: avoid_print
11-
1210
import 'dart:async';
1311

1412
import 'package:args/args.dart';
1513
import 'package:logging/logging.dart';
1614
import 'package:rohd/rohd.dart';
1715
import 'package:rohd_cosim/rohd_cosim.dart';
1816

19-
void main(List<String> args) async {
17+
Future<void> main(List<String> args) async {
2018
final parser = ArgParser()
2119
..addOption('port', mandatory: true)
2220
..addFlag('fail')
@@ -28,7 +26,7 @@ void main(List<String> args) async {
2826
final fail = results['fail'] as bool;
2927
final failAsync = results['failAsync'] as bool;
3028
final hang = results['hang'] as bool;
31-
await runCosim(port, fail: fail, failAsync: failAsync, hang: hang);
29+
await runCosim(port, dartFail: fail, failAsync: failAsync, hang: hang);
3230
}
3331

3432
class BottomMod extends ExternalSystemVerilogModule with Cosim {
@@ -50,34 +48,41 @@ class BottomMod extends ExternalSystemVerilogModule with Cosim {
5048
const bool enableLogging = true;
5149

5250
Future<void> runCosim(int port,
53-
{required bool fail, required bool failAsync, required bool hang}) async {
54-
// var portStuffDir = './test/port_stuff/';
55-
// var outDirPath = '$portStuffDir/tmp_output/';
56-
51+
{required bool dartFail,
52+
required bool failAsync,
53+
required bool hang,
54+
bool doPrint = true}) async {
5755
void expectEqual(dynamic a, dynamic b) {
5856
if (a != b) {
5957
throw Exception('$a != $b');
6058
}
6159
}
6260

63-
print('Building module...');
61+
void log(String message) {
62+
if (doPrint) {
63+
// ignore: avoid_print
64+
print(message);
65+
}
66+
}
67+
68+
log('Building module...');
6469
final a = Logic();
6570
final mod = BottomMod(a);
6671
await mod.build();
6772

6873
if (enableLogging) {
6974
Logger.root.level = Level.ALL;
70-
Logger.root.onRecord.listen(print);
75+
Logger.root.onRecord.listen((msg) => log(msg.toString()));
7176
}
7277

73-
print('Connecting to cosimulation on port $port...');
78+
log('Connecting to cosimulation on port $port...');
7479
await Cosim.connectCosimulation(
7580
CosimPortConfig(port, enableLogging: enableLogging));
7681

77-
print('Starting simulation...');
82+
log('Starting simulation...');
7883

7984
mod.aBar.changed.listen((event) {
80-
print('checking @ ${Simulator.time}');
85+
log('checking @ ${Simulator.time}');
8186
if (Simulator.time == 2) {
8287
expectEqual(event.newValue, LogicValue.zero);
8388
} else if (Simulator.time == 4) {
@@ -88,44 +93,44 @@ Future<void> runCosim(int port,
8893
});
8994

9095
Simulator.registerAction(2, () {
91-
print('putting 1');
96+
log('putting 1');
9297
a.put(1);
9398
});
9499
Simulator.registerAction(4, () {
95-
print('putting 0');
100+
log('putting 0');
96101
a.put(0);
97102
});
98103

99-
if (fail) {
100-
print('Setting up to fail on the dart side.');
104+
if (dartFail) {
105+
log('Setting up to fail on the dart side.');
101106
Simulator.registerAction(3, () {
102107
throw Exception('Failure intentionally injected');
103108
});
104109
}
105110

106111
if (failAsync) {
107-
print('Setting up to async fail on the dart side.');
112+
log('Setting up to async fail on the dart side.');
108113
unawaited(a.changed.first.then(
109114
(value) => throw Exception('Async failure intentionally injected')));
110115
}
111116

112117
if (hang) {
113-
print('Setting up to hang on the dart side.');
118+
log('Setting up to hang on the dart side.');
114119
Simulator.registerAction(3, () async {
115-
print('About to hang...');
120+
log('About to hang...');
116121
Simulator.injectAction(() async {
117122
await Future<void>.delayed(const Duration(seconds: 10));
118123
});
119124
});
120125
}
121126

122127
Simulator.registerEndOfSimulationAction(() {
123-
print('End of ROHD Simulation!');
128+
log('End of ROHD Simulation!');
124129
});
125130

126-
print('Done setting up vectors, launching simulation!');
131+
log('Done setting up vectors, launching simulation!');
127132

128133
await Simulator.run();
129134

130-
print('Simulation has completed!');
135+
log('Simulation has completed!');
131136
}

0 commit comments

Comments
 (0)