From cdbc9a38275123759fe7ba1cb86a446c16898f8b Mon Sep 17 00:00:00 2001 From: "Kimmel, Joshua1" Date: Wed, 11 Jun 2025 15:20:49 -0700 Subject: [PATCH 1/3] support for newer Linux distros --- lib/src/configs/cosim_wrap_config.dart | 54 +++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/src/configs/cosim_wrap_config.dart b/lib/src/configs/cosim_wrap_config.dart index 4b3e435..000a097 100644 --- a/lib/src/configs/cosim_wrap_config.dart +++ b/lib/src/configs/cosim_wrap_config.dart @@ -107,6 +107,8 @@ class CosimWrapConfig extends CosimProcessConfig { Cosim.registrees, dumpWavesString: dumpWavesString, ); + _createRequirementsTxt(directory: directory); + _pythonVEnvProcess(directory: directory); _createMakefile( directory: directory, simulator: systemVerilogSimulator, @@ -124,9 +126,59 @@ class CosimWrapConfig extends CosimProcessConfig { '-f', _cosimMakefileName, ], - environment: environment, + environment: { + if (environment != null) ...environment!, + 'PATH': + '${Directory(directory).absolute.path}/$_cosimVEnvName/bin:${Platform.environment['PATH']}', + 'PYTHON3': + '${Directory(directory).absolute.path}/$_cosimVEnvName/bin/python3', + }, + // environment: environment, ); + /// The name of the requirements.txt that gets generated. + static const _cosimRequirementsName = 'requirements.txt'; + + /// Generates a requirements.txt file that contains the Python requirements + /// for running Cosimulation (namely, cocotb). + static void _createRequirementsTxt({ + required String directory, + String cocotbVersion = '1.9.2', + }) { + final contents = [ + 'cocotb==$cocotbVersion', + ].join('\n'); + File('$directory/$_cosimRequirementsName').writeAsStringSync(contents); + } + + // The name of the Python venv that gets generated. + static const _cosimVEnvName = 'cosim_venv'; + + /// Generates a Python virtual with all necessary dependencies installed for + /// Cosimulation. + static void _pythonVEnvProcess({required String directory}) { + final pythonVEnvPath = '$directory/$_cosimVEnvName'; + + // create a Python virtual environment + final createVEnv = + Process.runSync('python3', ['-m', 'venv', pythonVEnvPath]); + if (createVEnv.exitCode != 0) { + throw Exception( + 'Failed to create Python virtual environment: ${createVEnv.stderr}'); + } + + // install cocotb in the virtual environment + final pipPath = '$pythonVEnvPath/bin/pip'; + final installCocotb = Process.runSync( + pipPath, + ['install', '-r', '$directory/$_cosimRequirementsName'], + environment: {'PATH': '$pythonVEnvPath/bin'}, + ); + if (installCocotb.exitCode != 0) { + throw Exception('Failed to install cocotb: ${installCocotb.stderr}'); + } + } + /// The name to use for the SystemVerilog wrapper. static const _wrapperName = 'cosim_wrapper'; From d8b6e61514f45378f28fdd5b332a5ef11d58b556 Mon Sep 17 00:00:00 2001 From: "Kimmel, Joshua1" Date: Mon, 16 Jun 2025 17:08:05 -0700 Subject: [PATCH 2/3] addressing feedback on PR --- lib/src/configs/cosim_wrap_config.dart | 27 ++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/src/configs/cosim_wrap_config.dart b/lib/src/configs/cosim_wrap_config.dart index 000a097..4a0f76b 100644 --- a/lib/src/configs/cosim_wrap_config.dart +++ b/lib/src/configs/cosim_wrap_config.dart @@ -66,6 +66,18 @@ class CosimWrapConfig extends CosimProcessConfig { /// the SystemVerilog simulator. final Map? environment; + /// Should Cosim create a Python virtual environment to run cocotb in. + /// + /// With this option, users do not need to have cocotb installed and can still + /// control the version of cocotb via [cocotbVersion]. + final bool usePythonVirtualEnvironment; + + /// The version of cocotb to install in the Python virtual environment. + /// + /// Only applicable if using the Python virtual environment + /// ([usePythonVirtualEnvironment]). + final String cocotbVersion; + /// Generates a SystemVerilog wrapper and a Makefile to be called by default. /// /// Generated files will be dumped into [directory]. Note that if your @@ -82,6 +94,8 @@ class CosimWrapConfig extends CosimProcessConfig { super.enableLogging, this.dumpWaves = false, this.environment, + this.usePythonVirtualEnvironment = true, + this.cocotbVersion = '1.9.2', super.throwOnUnexpectedEnd, }) { Cosim.generateConnector(directory: directory, enableLogging: enableLogging); @@ -107,8 +121,11 @@ class CosimWrapConfig extends CosimProcessConfig { Cosim.registrees, dumpWavesString: dumpWavesString, ); - _createRequirementsTxt(directory: directory); - _pythonVEnvProcess(directory: directory); + if (usePythonVirtualEnvironment) { + _createRequirementsTxt( + directory: directory, cocotbVersion: cocotbVersion); + _pythonVEnvProcess(directory: directory); + } _createMakefile( directory: directory, simulator: systemVerilogSimulator, @@ -143,7 +160,7 @@ class CosimWrapConfig extends CosimProcessConfig { /// for running Cosimulation (namely, cocotb). static void _createRequirementsTxt({ required String directory, - String cocotbVersion = '1.9.2', + required String cocotbVersion, }) { final contents = [ 'cocotb==$cocotbVersion', @@ -172,7 +189,9 @@ class CosimWrapConfig extends CosimProcessConfig { final installCocotb = Process.runSync( pipPath, ['install', '-r', '$directory/$_cosimRequirementsName'], - environment: {'PATH': '$pythonVEnvPath/bin'}, + environment: { + 'PATH': '$pythonVEnvPath/bin:${Platform.environment['PATH']}' + }, ); if (installCocotb.exitCode != 0) { throw Exception('Failed to install cocotb: ${installCocotb.stderr}'); From b5291b2bfe19a5e4ab2c8f7e6fa1676be3c980e9 Mon Sep 17 00:00:00 2001 From: "Kimmel, Joshua1" Date: Tue, 17 Jun 2025 17:20:35 -0700 Subject: [PATCH 3/3] more feedback items --- lib/src/configs/cosim_wrap_config.dart | 10 ++++++---- test/bus_test.dart | 19 +++++++++++++++++++ test/cosim_test_infra.dart | 6 ++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/src/configs/cosim_wrap_config.dart b/lib/src/configs/cosim_wrap_config.dart index 4a0f76b..3a57f29 100644 --- a/lib/src/configs/cosim_wrap_config.dart +++ b/lib/src/configs/cosim_wrap_config.dart @@ -145,10 +145,12 @@ class CosimWrapConfig extends CosimProcessConfig { ], environment: { if (environment != null) ...environment!, - 'PATH': - '${Directory(directory).absolute.path}/$_cosimVEnvName/bin:${Platform.environment['PATH']}', - 'PYTHON3': - '${Directory(directory).absolute.path}/$_cosimVEnvName/bin/python3', + if (usePythonVirtualEnvironment) + 'PATH': + '${Directory(directory).absolute.path}/$_cosimVEnvName/bin:${Platform.environment['PATH']}', + if (usePythonVirtualEnvironment) + 'PYTHON3': + '${Directory(directory).absolute.path}/$_cosimVEnvName/bin/python3', }, // environment: environment, ); diff --git a/test/bus_test.dart b/test/bus_test.dart index 300b989..19dcb3a 100644 --- a/test/bus_test.dart +++ b/test/bus_test.dart @@ -52,5 +52,24 @@ Future main() async { ]; await SimCompare.checkFunctionalVector(mod, vectors); }); + + test('simple bus - no Python venv', () async { + final mod = CosimBusMod(Logic(width: 4)); + await mod.build(); + + const dirName = 'simple_bus'; + + await CosimTestingInfrastructure.connectCosim(dirName, + systemVerilogSimulator: sim, usePythonVirtualEnvironment: false); + + final vectors = [ + Vector({'a': 0}, {'b': 0}), + Vector({'a': 0x3}, {'b': 0x3}), + if (sim != SystemVerilogSimulator.verilator) + Vector({'a': LogicValue.ofString('01xz')}, + {'b': LogicValue.ofString('01xz')}), + ]; + await SimCompare.checkFunctionalVector(mod, vectors); + }); }); } diff --git a/test/cosim_test_infra.dart b/test/cosim_test_infra.dart index b08a826..8717ee8 100644 --- a/test/cosim_test_infra.dart +++ b/test/cosim_test_infra.dart @@ -25,12 +25,16 @@ abstract class CosimTestingInfrastructure { /// /// Make sure to call [cleanupCosim] afterwards. If you set /// [cleanupAfterSimulationEnds] it will do it automatically for you. + /// [usePythonVirtualEnvironment] and [cocotbVersion] control how the Cosim + /// interacts with the host environment. static Future connectCosim( String testName, { required SystemVerilogSimulator systemVerilogSimulator, bool enableLogging = false, bool dumpWaves = false, bool cleanupAfterSimulationEnds = true, + bool usePythonVirtualEnvironment = true, + String cocotbVersion = '1.9.2', }) async { if (enableLogging) { Logger.root.level = Level.ALL; @@ -43,6 +47,8 @@ abstract class CosimTestingInfrastructure { directory: tempDirName(testName, systemVerilogSimulator), enableLogging: enableLogging, dumpWaves: dumpWaves, + usePythonVirtualEnvironment: usePythonVirtualEnvironment, + cocotbVersion: cocotbVersion, )); if (cleanupAfterSimulationEnds) {