scons: Add sim_object and enums arguments to SimObject().

This will explicitly declare what SimObject and Enum types need to be set
up in C++, which will make importing all the SimObject modules during
the setup phase of SCons uneccessary.

Change-Id: Id2d7603daf33b236ceaa0789e2f089f589d34e62
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/49406
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/SConscript b/src/SConscript
index 185829f..9cbfbdf 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -142,7 +142,8 @@
 
     fixed = False
 
-    def __init__(self, source, tags=None, add_tags=None):
+    def __init__(self, source, *, sim_objects=[], enums=[],
+            tags=None, add_tags=None):
         '''Specify the source file and any tags (automatically in
         the m5.objects package)'''
         super().__init__('m5.objects', source, tags, add_tags)
diff --git a/src/arch/amdgpu/gcn3/SConscript b/src/arch/amdgpu/gcn3/SConscript
index dc4660f..e8e0002 100644
--- a/src/arch/amdgpu/gcn3/SConscript
+++ b/src/arch/amdgpu/gcn3/SConscript
@@ -39,7 +39,7 @@
     Return()
 
 if env['TARGET_GPU_ISA'] == 'gcn3':
-    SimObject('X86GPUTLB.py')
+    SimObject('X86GPUTLB.py', sim_objects=['X86GPUTLB', 'TLBCoalescer'])
 
     Source('decoder.cc')
     Source('insts/gpu_static_inst.cc')
diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript
index ec1db57..b138212 100644
--- a/src/arch/arm/SConscript
+++ b/src/arch/arm/SConscript
@@ -93,17 +93,24 @@
 Source('tlbi_op.cc', tags='arm isa')
 Source('utility.cc', tags='arm isa')
 
-SimObject('ArmDecoder.py', tags='arm isa')
-SimObject('ArmFsWorkload.py', tags='arm isa')
-SimObject('ArmInterrupts.py', tags='arm isa')
-SimObject('ArmISA.py', tags='arm isa')
-SimObject('ArmMMU.py', tags='arm isa')
-SimObject('ArmNativeTrace.py', tags='arm isa')
-SimObject('ArmSemihosting.py', tags='arm isa')
-SimObject('ArmSeWorkload.py', tags='arm isa')
-SimObject('ArmSystem.py', tags='arm isa')
-SimObject('ArmTLB.py', tags='arm isa')
-SimObject('ArmPMU.py', tags='arm isa')
+SimObject('ArmDecoder.py', sim_objects=['ArmDecoder'], tags='arm isa')
+SimObject('ArmFsWorkload.py', sim_objects=[
+    'ArmFsWorkload', 'ArmFsLinux', 'ArmFsFreebsd'],
+    enums=['ArmMachineType'], tags='arm isa')
+SimObject('ArmInterrupts.py', sim_objects=['ArmInterrupts'], tags='arm isa')
+SimObject('ArmISA.py', sim_objects=['ArmISA'], enums=['DecoderFlavor'],
+    tags='arm isa')
+SimObject('ArmMMU.py', sim_objects=['ArmTableWalker', 'ArmMMU'],
+    tags='arm isa')
+SimObject('ArmNativeTrace.py', sim_objects=['ArmNativeTrace'], tags='arm isa')
+SimObject('ArmSemihosting.py', sim_objects=['ArmSemihosting'], tags='arm isa')
+SimObject('ArmSeWorkload.py', sim_objects=[
+    'ArmSEWorkload', 'ArmEmuLinux', 'ArmEmuFreebsd'], tags='arm isa')
+SimObject('ArmSystem.py', sim_objects=['ArmSystem', 'ArmRelease'],
+    enums=['ArmExtension'], tags='arm isa')
+SimObject('ArmTLB.py', sim_objects=['ArmTLB'], enums=['ArmLookupLevel'],
+    tags='arm isa')
+SimObject('ArmPMU.py', sim_objects=['ArmPMU'], tags='arm isa')
 
 DebugFlag('Arm', tags='arm isa')
 DebugFlag('ArmTme', 'Transactional Memory Extension', tags='arm isa')
diff --git a/src/arch/arm/fastmodel/CortexA76/SConscript b/src/arch/arm/fastmodel/CortexA76/SConscript
index 376d068..ce51268 100644
--- a/src/arch/arm/fastmodel/CortexA76/SConscript
+++ b/src/arch/arm/fastmodel/CortexA76/SConscript
@@ -37,7 +37,10 @@
                               'ExportedClockRateControlProtocol.lisa')
                           ).prepare_env(env)
 
-SimObject('FastModelCortexA76.py')
+SimObject('FastModelCortexA76.py', sim_objects=[
+    'FastModelCortexA76', 'FastModelCortexA76Cluster'] +
+    [f'FastModelScxEvsCortexA76x{num}' for num in (1, 2, 3, 4)] +
+    [f'FastModelCortexA76x{num}' for num in (1, 2, 3, 4)])
 Source('cortex_a76.cc')
 Source('evs.cc')
 Source('thread_context.cc')
diff --git a/src/arch/arm/fastmodel/CortexR52/SConscript b/src/arch/arm/fastmodel/CortexR52/SConscript
index 0b81fbb..4e5e147 100644
--- a/src/arch/arm/fastmodel/CortexR52/SConscript
+++ b/src/arch/arm/fastmodel/CortexR52/SConscript
@@ -38,7 +38,10 @@
                           protocol_dir.File('SignalInterruptProtocol.lisa')
                           ).prepare_env(env)
 
-SimObject('FastModelCortexR52.py')
+SimObject('FastModelCortexR52.py', sim_objects=[
+    'FastModelCortexR52', 'FastModelCortexR52Cluster'] +
+    [f'FastModelScxEvsCortexR52x{num}' for num in (1, 2, 3, 4)] +
+    [f'FastModelCortexR52x{num}' for num in (1, 2, 3, 4)])
 Source('cortex_r52.cc')
 Source('evs.cc')
 Source('thread_context.cc')
diff --git a/src/arch/arm/fastmodel/GIC/SConscript b/src/arch/arm/fastmodel/GIC/SConscript
index 94cfbb9..2a95145 100644
--- a/src/arch/arm/fastmodel/GIC/SConscript
+++ b/src/arch/arm/fastmodel/GIC/SConscript
@@ -33,5 +33,5 @@
 ArmFastModelComponent(File('GIC.sgproj'), File('GIC.lisa'),
                       protocol_dir.File('SignalInterruptProtocol.lisa')
                       ).prepare_env(env)
-SimObject('FastModelGIC.py')
+SimObject('FastModelGIC.py', sim_objects=['SCFastModelGIC', 'FastModelGIC'])
 Source('gic.cc')
diff --git a/src/arch/arm/fastmodel/PL330_DMAC/SConscript b/src/arch/arm/fastmodel/PL330_DMAC/SConscript
index 4640b93..3e41e05 100644
--- a/src/arch/arm/fastmodel/PL330_DMAC/SConscript
+++ b/src/arch/arm/fastmodel/PL330_DMAC/SConscript
@@ -33,5 +33,5 @@
 ArmFastModelComponent(File('PL330.sgproj'), File('PL330.lisa'),
                       protocol_dir.File('SignalInterruptProtocol.lisa')
                       ).prepare_env(env)
-SimObject('FastModelPL330.py')
+SimObject('FastModelPL330.py', sim_objects=['FastModelPL330'])
 Source('pl330.cc')
diff --git a/src/arch/arm/fastmodel/SConscript b/src/arch/arm/fastmodel/SConscript
index c55d897..63b1b16 100644
--- a/src/arch/arm/fastmodel/SConscript
+++ b/src/arch/arm/fastmodel/SConscript
@@ -353,7 +353,8 @@
 PySource('m5', 'arm_fast_model.py')
 Source('fastmodel.cc')
 
-SimObject('FastModel.py')
+SimObject('FastModel.py', sim_objects=[
+    'AmbaToTlmBridge64', 'AmbaFromTlmBridge64'])
 Source('amba_to_tlm_bridge.cc')
 Source('amba_from_tlm_bridge.cc')
 
diff --git a/src/arch/arm/fastmodel/iris/SConscript b/src/arch/arm/fastmodel/iris/SConscript
index 9586f0f..6635ca0 100644
--- a/src/arch/arm/fastmodel/iris/SConscript
+++ b/src/arch/arm/fastmodel/iris/SConscript
@@ -28,7 +28,8 @@
 if not env['USE_ARM_FASTMODEL']:
     Return()
 
-SimObject('Iris.py')
+SimObject('Iris.py', sim_objects=[
+    'IrisTLB', 'IrisMMU', 'IrisInterrupts', 'IrisISA', 'IrisBaseCPU'])
 Source('cpu.cc')
 Source('interrupts.cc')
 Source('isa.cc')
diff --git a/src/arch/arm/kvm/SConscript b/src/arch/arm/kvm/SConscript
index 3adb45c..44134a4 100644
--- a/src/arch/arm/kvm/SConscript
+++ b/src/arch/arm/kvm/SConscript
@@ -43,15 +43,15 @@
 if not (env['USE_KVM'] and env['KVM_ISA'] == 'arm'):
     Return()
 
-SimObject('KvmGic.py', tags='arm isa')
+SimObject('KvmGic.py', sim_objects=['MuxingKvmGic'], tags='arm isa')
 Source('gic.cc', tags='arm isa')
 
-SimObject('BaseArmKvmCPU.py', tags='arm isa')
+SimObject('BaseArmKvmCPU.py', sim_objects=['BaseArmKvmCPU'], tags='arm isa')
 Source('base_cpu.cc', tags='arm isa')
 
 if host_isa == "armv7l":
-    SimObject('ArmKvmCPU.py', tags='arm isa')
+    SimObject('ArmKvmCPU.py', sim_objects=['ArmKvmCPU'], tags='arm isa')
     Source('arm_cpu.cc', tags='arm isa')
 elif host_isa == "aarch64":
-    SimObject('ArmV8KvmCPU.py', tags='arm isa')
+    SimObject('ArmV8KvmCPU.py', sim_objects=['ArmV8KvmCPU'], tags='arm isa')
     Source('armv8_cpu.cc', tags='arm isa')
diff --git a/src/arch/arm/tracers/SConscript b/src/arch/arm/tracers/SConscript
index 3ea03aa..a509b22 100644
--- a/src/arch/arm/tracers/SConscript
+++ b/src/arch/arm/tracers/SConscript
@@ -35,7 +35,8 @@
 
 Import('*')
 
-SimObject('TarmacTrace.py', tags='arm isa')
+SimObject('TarmacTrace.py', sim_objects=['TarmacParser', 'TarmacTracer'],
+        tags='arm isa')
 Source('tarmac_base.cc', tags='arm isa')
 Source('tarmac_parser.cc', tags='arm isa')
 Source('tarmac_tracer.cc', tags='arm isa')
diff --git a/src/arch/generic/SConscript b/src/arch/generic/SConscript
index 140ea6c..88d8f3b 100644
--- a/src/arch/generic/SConscript
+++ b/src/arch/generic/SConscript
@@ -41,11 +41,11 @@
 Source('htm.cc')
 Source('mmu.cc')
 
-SimObject('BaseInterrupts.py')
-SimObject('BaseISA.py')
-SimObject('BaseMMU.py')
-SimObject('BaseTLB.py')
-SimObject('InstDecoder.py')
+SimObject('BaseInterrupts.py', sim_objects=['BaseInterrupts'])
+SimObject('BaseISA.py', sim_objects=['BaseISA'])
+SimObject('BaseMMU.py', sim_objects=['BaseMMU'])
+SimObject('BaseTLB.py', sim_objects=['BaseTLB'], enums=['TypeTLB'])
+SimObject('InstDecoder.py', sim_objects=['InstDecoder'])
 
 DebugFlag('PageTableWalker',
           "Page table walker state machine debugging")
diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript
index ab903fa..2a4110a 100644
--- a/src/arch/mips/SConscript
+++ b/src/arch/mips/SConscript
@@ -43,12 +43,13 @@
 Source('tlb.cc', tags='mips isa')
 Source('utility.cc', tags='mips isa')
 
-SimObject('MipsDecoder.py', tags='mips isa')
-SimObject('MipsInterrupts.py', tags='mips isa')
-SimObject('MipsISA.py', tags='mips isa')
-SimObject('MipsMMU.py', tags='mips isa')
-SimObject('MipsSeWorkload.py', tags='mips isa')
-SimObject('MipsTLB.py', tags='mips isa')
+SimObject('MipsDecoder.py', sim_objects=['MipsDecoder'], tags='mips isa')
+SimObject('MipsInterrupts.py', sim_objects=['MipsInterrupts'], tags='mips isa')
+SimObject('MipsISA.py', sim_objects=['MipsISA'], tags='mips isa')
+SimObject('MipsMMU.py', sim_objects=['MipsMMU'], tags='mips isa')
+SimObject('MipsSeWorkload.py', sim_objects=['MipsSEWorkload', 'MipsEmuLinux'],
+    tags='mips isa')
+SimObject('MipsTLB.py', sim_objects=['MipsTLB'], tags='mips isa')
 
 DebugFlag('MipsPRA', tags='mips isa')
 
diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript
index 0b1b9ea..7dd4089 100644
--- a/src/arch/power/SConscript
+++ b/src/arch/power/SConscript
@@ -46,12 +46,14 @@
 Source('se_workload.cc', tags='power isa')
 Source('tlb.cc', tags='power isa')
 
-SimObject('PowerDecoder.py', tags='power isa')
-SimObject('PowerInterrupts.py', tags='power isa')
-SimObject('PowerISA.py', tags='power isa')
-SimObject('PowerMMU.py', tags='power isa')
-SimObject('PowerSeWorkload.py', tags='power isa')
-SimObject('PowerTLB.py', tags='power isa')
+SimObject('PowerDecoder.py', sim_objects=['PowerDecoder'], tags='power isa')
+SimObject('PowerInterrupts.py', sim_objects=['PowerInterrupts'],
+    tags='power isa')
+SimObject('PowerISA.py', sim_objects=['PowerISA'], tags='power isa')
+SimObject('PowerMMU.py', sim_objects=['PowerMMU'], tags='power isa')
+SimObject('PowerSeWorkload.py', sim_objects=[
+    'PowerSEWorkload', 'PowerEmuLinux'], tags='power isa')
+SimObject('PowerTLB.py', sim_objects=['PowerTLB'], tags='power isa')
 
 DebugFlag('Power', tags='power isa')
 
diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript
index ddd7c6b..8b7942e 100644
--- a/src/arch/riscv/SConscript
+++ b/src/arch/riscv/SConscript
@@ -60,15 +60,19 @@
 
 Source('bare_metal/fs_workload.cc', tags='riscv isa')
 
-SimObject('PMAChecker.py', tags='riscv isa')
-SimObject('PMP.py', tags='riscv isa')
-SimObject('RiscvDecoder.py', tags='riscv isa')
-SimObject('RiscvFsWorkload.py', tags='riscv isa')
-SimObject('RiscvInterrupts.py', tags='riscv isa')
-SimObject('RiscvISA.py', tags='riscv isa')
-SimObject('RiscvMMU.py', tags='riscv isa')
-SimObject('RiscvSeWorkload.py', tags='riscv isa')
-SimObject('RiscvTLB.py', tags='riscv isa')
+SimObject('PMAChecker.py', sim_objects=['PMAChecker'], tags='riscv isa')
+SimObject('PMP.py', sim_objects=['PMP'], tags='riscv isa')
+SimObject('RiscvDecoder.py', sim_objects=['RiscvDecoder'], tags='riscv isa')
+SimObject('RiscvFsWorkload.py', sim_objects=['RiscvBareMetal', 'RiscvLinux'],
+    tags='riscv isa')
+SimObject('RiscvInterrupts.py', sim_objects=['RiscvInterrupts'],
+    tags='riscv isa')
+SimObject('RiscvISA.py', sim_objects=['RiscvISA'], tags='riscv isa')
+SimObject('RiscvMMU.py', sim_objects=['RiscvMMU'], tags='riscv isa')
+SimObject('RiscvSeWorkload.py', sim_objects=[
+    'RiscvSEWorkload', 'RiscvEmuLinux'], tags='riscv isa')
+SimObject('RiscvTLB.py', sim_objects=['RiscvPagetableWalker', 'RiscvTLB'],
+    tags='riscv isa')
 
 DebugFlag('RiscvMisc', tags='riscv isa')
 DebugFlag('PMP', tags='riscv isa')
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript
index e69754c..c25d33f 100644
--- a/src/arch/sparc/SConscript
+++ b/src/arch/sparc/SConscript
@@ -43,14 +43,18 @@
 Source('tlb.cc', tags='sparc isa')
 Source('ua2005.cc', tags='sparc isa')
 
-SimObject('SparcDecoder.py', tags='sparc isa')
-SimObject('SparcFsWorkload.py', tags='sparc isa')
-SimObject('SparcInterrupts.py', tags='sparc isa')
-SimObject('SparcISA.py', tags='sparc isa')
-SimObject('SparcMMU.py', tags='sparc isa')
-SimObject('SparcNativeTrace.py', tags='sparc isa')
-SimObject('SparcSeWorkload.py', tags='sparc isa')
-SimObject('SparcTLB.py', tags='sparc isa')
+SimObject('SparcDecoder.py', sim_objects=['SparcDecoder'], tags='sparc isa')
+SimObject('SparcFsWorkload.py', sim_objects=['SparcFsWorkload'],
+    tags='sparc isa')
+SimObject('SparcInterrupts.py', sim_objects=['SparcInterrupts'],
+    tags='sparc isa')
+SimObject('SparcISA.py', sim_objects=['SparcISA'], tags='sparc isa')
+SimObject('SparcMMU.py', sim_objects=['SparcMMU'], tags='sparc isa')
+SimObject('SparcNativeTrace.py', sim_objects=['SparcNativeTrace'],
+    tags='sparc isa')
+SimObject('SparcSeWorkload.py', sim_objects=[
+    'SparcSEWorkload', 'SparcEmuLinux'], tags='sparc isa')
+SimObject('SparcTLB.py', sim_objects=['SparcTLB'], tags='sparc isa')
 
 DebugFlag('Sparc', "Generic SPARC ISA stuff", tags='sparc isa')
 DebugFlag('RegisterWindows', "Register window manipulation", tags='sparc isa')
diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript
index 50ec117..d1ec549 100644
--- a/src/arch/x86/SConscript
+++ b/src/arch/x86/SConscript
@@ -61,14 +61,16 @@
 Source('types.cc', tags='x86 isa')
 Source('utility.cc', tags='x86 isa')
 
-SimObject('X86SeWorkload.py', tags='x86 isa')
-SimObject('X86FsWorkload.py', tags='x86 isa')
-SimObject('X86Decoder.py', tags='x86 isa')
-SimObject('X86ISA.py', tags='x86 isa')
-SimObject('X86LocalApic.py', tags='x86 isa')
-SimObject('X86MMU.py', tags='x86 isa')
-SimObject('X86NativeTrace.py', tags='x86 isa')
-SimObject('X86TLB.py', tags='x86 isa')
+SimObject('X86SeWorkload.py', sim_objects=['X86EmuLinux'], tags='x86 isa')
+SimObject('X86FsWorkload.py', sim_objects=['X86FsWorkload', 'X86FsLinux'],
+    tags='x86 isa')
+SimObject('X86Decoder.py', sim_objects=['X86Decoder'], tags='x86 isa')
+SimObject('X86ISA.py', sim_objects=['X86ISA'], tags='x86 isa')
+SimObject('X86LocalApic.py', sim_objects=['X86LocalApic'], tags='x86 isa')
+SimObject('X86MMU.py', sim_objects=['X86MMU'], tags='x86 isa')
+SimObject('X86NativeTrace.py', sim_objects=['X86NativeTrace'], tags='x86 isa')
+SimObject('X86TLB.py', sim_objects=['X86PagetableWalker', 'X86TLB'],
+    tags='x86 isa')
 
 DebugFlag('LocalApic', "Local APIC debugging", tags='x86 isa')
 DebugFlag('X86', "Generic X86 ISA debugging", tags='x86 isa')
diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript
index 6ecc830..9dfdfb6 100644
--- a/src/arch/x86/bios/SConscript
+++ b/src/arch/x86/bios/SConscript
@@ -39,17 +39,36 @@
 
 # The table generated by the bootloader using the BIOS and passed to
 # the operating system which maps out physical memory.
-SimObject('E820.py', tags='x86 isa')
+SimObject('E820.py', sim_objects=['X86E820Entry', 'X86E820Table'],
+    tags='x86 isa')
 Source('e820.cc', tags='x86 isa')
 
 # The DMI tables.
-SimObject('SMBios.py', tags='x86 isa')
+SimObject('SMBios.py', sim_objects=[
+    'X86SMBiosSMBiosStructure', 'X86SMBiosBiosInformation',
+    'X86SMBiosSMBiosTable'],
+    enums=['Characteristic', 'ExtCharacteristic'], tags='x86 isa')
 Source('smbios.cc', tags='x86 isa')
 
 # Intel Multiprocessor Specification Configuration Table
-SimObject('IntelMP.py', tags='x86 isa')
+SimObject('IntelMP.py', sim_objects=[
+    'X86IntelMPFloatingPointer', 'X86IntelMPConfigTable',
+    'X86IntelMPBaseConfigEntry', 'X86IntelMPExtConfigEntry',
+    'X86IntelMPProcessor', 'X86IntelMPBus', 'X86IntelMPIOAPIC',
+    'X86IntelMPIOIntAssignment', 'X86IntelMPLocalIntAssignment',
+    'X86IntelMPAddrSpaceMapping', 'X86IntelMPBusHierarchy',
+    'X86IntelMPCompatAddrSpaceMod'],
+    enums=['X86IntelMPInterruptType', 'X86IntelMPPolarity',
+        'X86IntelMPTriggerMode', 'X86IntelMPAddressType',
+        'X86IntelMPRangeList'],
+    tags='x86 isa')
 Source('intelmp.cc', tags='x86 isa')
 
 # ACPI system description tables
-SimObject('ACPI.py', tags='x86 isa')
+SimObject('ACPI.py', sim_objects=[
+    'X86ACPISysDescTable', 'X86ACPIRSDT', 'X86ACPIXSDT',
+    'X86ACPIMadtRecord', 'X86ACPIMadt', 'X86ACPIMadtLAPIC',
+    'X86ACPIMadtIOAPIC', 'X86ACPIMadtIntSourceOverride', 'X86ACPIMadtNMI',
+    'X86ACPIMadtLAPICOverride', 'X86ACPIRSDP'],
+    tags='x86 isa')
 Source('acpi.cc', tags='x86 isa')
diff --git a/src/arch/x86/kvm/SConscript b/src/arch/x86/kvm/SConscript
index 4518f72..0b3d3c8 100644
--- a/src/arch/x86/kvm/SConscript
+++ b/src/arch/x86/kvm/SConscript
@@ -40,5 +40,5 @@
 if not env['USE_KVM'] or env['TARGET_ISA'] != env['KVM_ISA']:
     Return()
 
-SimObject('X86KvmCPU.py', tags='x86 isa')
+SimObject('X86KvmCPU.py', sim_objects=['X86KvmCPU'], tags='x86 isa')
 Source('x86_cpu.cc', tags='x86 isa')
diff --git a/src/base/SConscript b/src/base/SConscript
index bdc8932..c49e2ae 100644
--- a/src/base/SConscript
+++ b/src/base/SConscript
@@ -28,7 +28,7 @@
 
 Import('*')
 
-SimObject('Graphics.py')
+SimObject('Graphics.py', enums=['ImageFormat'])
 GTest('amo.test', 'amo.test.cc')
 Source('atomicio.cc', add_tags='gem5 trace')
 GTest('atomicio.test', 'atomicio.test.cc', 'atomicio.cc')
diff --git a/src/base/filters/SConscript b/src/base/filters/SConscript
index d8da413..b95d51b 100644
--- a/src/base/filters/SConscript
+++ b/src/base/filters/SConscript
@@ -29,7 +29,10 @@
 
 Import('*')
 
-SimObject('BloomFilters.py')
+SimObject('BloomFilters.py', sim_objects=[
+    'BloomFilterBase', 'BloomFilterBlock', 'BloomFilterMultiBitSel',
+    'BloomFilterBulk', 'BloomFilterH3', 'BloomFilterMulti',
+    'BloomFilterPerfect'])
 
 Source('block_bloom_filter.cc')
 Source('bulk_bloom_filter.cc')
diff --git a/src/base/vnc/SConscript b/src/base/vnc/SConscript
index 5bb5dd5..c70527c 100644
--- a/src/base/vnc/SConscript
+++ b/src/base/vnc/SConscript
@@ -37,7 +37,7 @@
 
 Import('*')
 
-SimObject('Vnc.py')
+SimObject('Vnc.py', sim_objects=['VncInput', 'VncServer'])
 Source('vncinput.cc')
 Source('vncserver.cc')
 DebugFlag('VNC')
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index 0aaca12..4dcec7c 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -82,22 +82,27 @@
 Source('func_unit.cc')
 Source('pc_event.cc')
 
-SimObject('FuncUnit.py')
-SimObject('StaticInstFlags.py')
+SimObject('FuncUnit.py', sim_objects=['OpDesc', 'FUDesc'], enums=['OpClass'])
+SimObject('StaticInstFlags.py', enums=['StaticInstFlags'])
 
 if env['TARGET_ISA'] == 'null':
     Return()
 
 # Only build the protobuf instructions tracer if we have protobuf support.
 if env['HAVE_PROTOBUF']:
-    SimObject('InstPBTrace.py')
+    SimObject('InstPBTrace.py', sim_objects=['InstPBTrace'])
     Source('inst_pb_trace.cc')
 
-SimObject('CheckerCPU.py')
+SimObject('CheckerCPU.py', sim_objects=['CheckerCPU'])
 
-SimObject('BaseCPU.py')
-SimObject('CPUTracers.py')
-SimObject('TimingExpr.py')
+SimObject('BaseCPU.py', sim_objects=['BaseCPU'])
+SimObject('CPUTracers.py', sim_objects=[
+    'ExeTracer', 'IntelTrace', 'NativeTrace'])
+SimObject('TimingExpr.py', sim_objects=[
+    'TimingExpr', 'TimingExprLiteral', 'TimingExprSrcReg',
+    'TimingExprReadIntReg', 'TimingExprLet', 'TimingExprRef', 'TimingExprUn',
+    'TimingExprBin', 'TimingExprIf'],
+    enums=['TimingExprOp'])
 
 Source('activity.cc')
 Source('base.cc')
@@ -114,6 +119,6 @@
 Source('thread_state.cc')
 Source('timing_expr.cc')
 
-SimObject('DummyChecker.py')
+SimObject('DummyChecker.py', sim_objects=['DummyChecker'])
 Source('checker/cpu.cc')
 DebugFlag('Checker')
diff --git a/src/cpu/kvm/SConscript b/src/cpu/kvm/SConscript
index 1b90408..c8ade6e 100644
--- a/src/cpu/kvm/SConscript
+++ b/src/cpu/kvm/SConscript
@@ -40,8 +40,8 @@
 if not env['USE_KVM'] or env['TARGET_ISA'] != env['KVM_ISA']:
     Return()
 
-SimObject('KvmVM.py')
-SimObject('BaseKvmCPU.py')
+SimObject('KvmVM.py', sim_objects=['KvmVM'])
+SimObject('BaseKvmCPU.py', sim_objects=['BaseKvmCPU'])
 
 Source('base.cc')
 Source('device.cc')
diff --git a/src/cpu/minor/SConscript b/src/cpu/minor/SConscript
index 75cc940..090ac44 100644
--- a/src/cpu/minor/SConscript
+++ b/src/cpu/minor/SConscript
@@ -41,7 +41,10 @@
 Import('*')
 
 if 'MinorCPU' in env['CPU_MODELS']:
-    SimObject('MinorCPU.py')
+    SimObject('MinorCPU.py', sim_objects=[
+        'MinorOpClass', 'MinorOpClassSet', 'MinorFUTiming', 'MinorFU',
+        'MinorFUPool', 'MinorCPU'],
+        enums=['ThreadPolicy'])
 
     Source('activity.cc')
     Source('cpu.cc')
diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript
index c61c7cf..a20e30d 100755
--- a/src/cpu/o3/SConscript
+++ b/src/cpu/o3/SConscript
@@ -31,9 +31,10 @@
 Import('*')
 
 if 'O3CPU' in env['CPU_MODELS']:
-    SimObject('FUPool.py')
+    SimObject('FUPool.py', sim_objects=['FUPool'])
     SimObject('FuncUnitConfig.py')
-    SimObject('O3CPU.py')
+    SimObject('O3CPU.py', sim_objects=['O3CPU'], enums=[
+        'SMTFetchPolicy', 'SMTQueuePolicy', 'CommitPolicy'])
 
     Source('commit.cc')
     Source('cpu.cc')
@@ -73,5 +74,5 @@
         'IQ', 'ROB', 'FreeList', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit',
         'DynInst', 'O3CPU', 'Activity', 'Scoreboard', 'Writeback' ])
 
-    SimObject('O3Checker.py')
+    SimObject('O3Checker.py', sim_objects=['O3Checker'])
     Source('checker.cc')
diff --git a/src/cpu/o3/probe/SConscript b/src/cpu/o3/probe/SConscript
index 92195b8..bd06b62 100644
--- a/src/cpu/o3/probe/SConscript
+++ b/src/cpu/o3/probe/SConscript
@@ -38,11 +38,11 @@
 Import('*')
 
 if 'O3CPU' in env['CPU_MODELS']:
-    SimObject('SimpleTrace.py')
+    SimObject('SimpleTrace.py', sim_objects=['SimpleTrace'])
     Source('simple_trace.cc')
     DebugFlag('SimpleTrace')
 
     if env['HAVE_PROTOBUF']:
-        SimObject('ElasticTrace.py')
+        SimObject('ElasticTrace.py', sim_objects=['ElasticTrace'])
         Source('elastic_trace.cc')
         DebugFlag('ElasticTrace')
diff --git a/src/cpu/pred/SConscript b/src/cpu/pred/SConscript
index fcc32e9..ee25b0c 100644
--- a/src/cpu/pred/SConscript
+++ b/src/cpu/pred/SConscript
@@ -31,7 +31,20 @@
 if env['TARGET_ISA'] == 'null':
     Return()
 
-SimObject('BranchPredictor.py')
+SimObject('BranchPredictor.py', sim_objects=[
+    'IndirectPredictor', 'SimpleIndirectPredictor', 'BranchPredictor',
+    'LocalBP', 'TournamentBP', 'BiModeBP', 'TAGEBase', 'TAGE', 'LoopPredictor',
+    'TAGE_SC_L_TAGE', 'TAGE_SC_L_TAGE_64KB', 'TAGE_SC_L_TAGE_8KB',
+    'LTAGE', 'TAGE_SC_L_LoopPredictor', 'StatisticalCorrector', 'TAGE_SC_L',
+    'TAGE_SC_L_64KB_StatisticalCorrector',
+    'TAGE_SC_L_8KB_StatisticalCorrector',
+    'TAGE_SC_L_64KB', 'TAGE_SC_L_8KB', 'MultiperspectivePerceptron',
+    'MultiperspectivePerceptron8KB', 'MultiperspectivePerceptron64KB',
+    'MPP_TAGE', 'MPP_LoopPredictor', 'MPP_StatisticalCorrector',
+    'MultiperspectivePerceptronTAGE', 'MPP_StatisticalCorrector_64KB',
+    'MultiperspectivePerceptronTAGE64KB', 'MPP_TAGE_8KB',
+    'MPP_LoopPredictor_8KB', 'MPP_StatisticalCorrector_8KB',
+    'MultiperspectivePerceptronTAGE8KB'])
 
 DebugFlag('Indirect')
 Source('bpred_unit.cc')
diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript
index 80286ec..b953d1f 100644
--- a/src/cpu/simple/SConscript
+++ b/src/cpu/simple/SConscript
@@ -31,18 +31,18 @@
 need_simple_base = False
 if 'AtomicSimpleCPU' in env['CPU_MODELS']:
     need_simple_base = True
-    SimObject('AtomicSimpleCPU.py')
+    SimObject('AtomicSimpleCPU.py', sim_objects=['AtomicSimpleCPU'])
     Source('atomic.cc')
 
     # The NonCachingSimpleCPU is really an atomic CPU in
     # disguise. It's therefore always enabled when the atomic CPU is
     # enabled.
-    SimObject('NonCachingSimpleCPU.py')
+    SimObject('NonCachingSimpleCPU.py', sim_objects=['NonCachingSimpleCPU'])
     Source('noncaching.cc')
 
 if 'TimingSimpleCPU' in env['CPU_MODELS']:
     need_simple_base = True
-    SimObject('TimingSimpleCPU.py')
+    SimObject('TimingSimpleCPU.py', sim_objects=['TimingSimpleCPU'])
     Source('timing.cc')
 
 if 'AtomicSimpleCPU' in env['CPU_MODELS'] or \
@@ -51,4 +51,4 @@
 
 if need_simple_base:
     Source('base.cc')
-    SimObject('BaseSimpleCPU.py')
+    SimObject('BaseSimpleCPU.py', sim_objects=['BaseSimpleCPU'])
diff --git a/src/cpu/simple/probes/SConscript b/src/cpu/simple/probes/SConscript
index ca685f0..eae6a45 100644
--- a/src/cpu/simple/probes/SConscript
+++ b/src/cpu/simple/probes/SConscript
@@ -29,5 +29,5 @@
 Import('*')
 
 if 'AtomicSimpleCPU' in env['CPU_MODELS']:
-    SimObject('SimPoint.py')
+    SimObject('SimPoint.py', sim_objects=['SimPoint'])
     Source('simpoint.cc')
diff --git a/src/cpu/testers/directedtest/SConscript b/src/cpu/testers/directedtest/SConscript
index 01e778f..e6453f9 100644
--- a/src/cpu/testers/directedtest/SConscript
+++ b/src/cpu/testers/directedtest/SConscript
@@ -38,7 +38,9 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('RubyDirectedTester.py')
+SimObject('RubyDirectedTester.py', sim_objects=[
+    'DirectedGenerator', 'SeriesRequestGenerator', 'InvalidateGenerator',
+    'RubyDirectedTester'])
 
 Source('RubyDirectedTester.cc')
 Source('DirectedGenerator.cc')
diff --git a/src/cpu/testers/garnet_synthetic_traffic/SConscript b/src/cpu/testers/garnet_synthetic_traffic/SConscript
index e55a639..b1f7c8d 100644
--- a/src/cpu/testers/garnet_synthetic_traffic/SConscript
+++ b/src/cpu/testers/garnet_synthetic_traffic/SConscript
@@ -31,7 +31,7 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('GarnetSyntheticTraffic.py')
+SimObject('GarnetSyntheticTraffic.py', sim_objects=['GarnetSyntheticTraffic'])
 
 Source('GarnetSyntheticTraffic.cc')
 
diff --git a/src/cpu/testers/gpu_ruby_test/SConscript b/src/cpu/testers/gpu_ruby_test/SConscript
index 5dcfbcb..a84e9f8 100644
--- a/src/cpu/testers/gpu_ruby_test/SConscript
+++ b/src/cpu/testers/gpu_ruby_test/SConscript
@@ -39,12 +39,12 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('ProtocolTester.py')
-SimObject('CpuThread.py')
-SimObject('DmaThread.py')
-SimObject('GpuWavefront.py')
-SimObject('TesterThread.py')
-SimObject('TesterDma.py')
+SimObject('ProtocolTester.py', sim_objects=['ProtocolTester'])
+SimObject('CpuThread.py', sim_objects=['CpuThread'])
+SimObject('DmaThread.py', sim_objects=['DmaThread'])
+SimObject('GpuWavefront.py', sim_objects=['GpuWavefront'])
+SimObject('TesterThread.py', sim_objects=['TesterThread'])
+SimObject('TesterDma.py', sim_objects=['TesterDma'])
 
 Source('address_manager.cc')
 Source('episode.cc')
diff --git a/src/cpu/testers/memtest/SConscript b/src/cpu/testers/memtest/SConscript
index 973d204..51e443b 100644
--- a/src/cpu/testers/memtest/SConscript
+++ b/src/cpu/testers/memtest/SConscript
@@ -29,7 +29,7 @@
 Import('*')
 
 #if 'O3CPU' in env['CPU_MODELS']:
-SimObject('MemTest.py')
+SimObject('MemTest.py', sim_objects=['MemTest'])
 
 Source('memtest.cc')
 
diff --git a/src/cpu/testers/rubytest/SConscript b/src/cpu/testers/rubytest/SConscript
index 70a4f48..87c38cc 100644
--- a/src/cpu/testers/rubytest/SConscript
+++ b/src/cpu/testers/rubytest/SConscript
@@ -38,7 +38,7 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('RubyTester.py')
+SimObject('RubyTester.py', sim_objects=['RubyTester'])
 
 Source('RubyTester.cc')
 Source('Check.cc')
diff --git a/src/cpu/testers/traffic_gen/SConscript b/src/cpu/testers/traffic_gen/SConscript
index a2670e7..3ac7872 100644
--- a/src/cpu/testers/traffic_gen/SConscript
+++ b/src/cpu/testers/traffic_gen/SConscript
@@ -53,19 +53,20 @@
 Source('strided_gen.cc')
 
 DebugFlag('TrafficGen')
-SimObject('BaseTrafficGen.py')
+SimObject('BaseTrafficGen.py', sim_objects=['BaseTrafficGen'],
+        enums=['StreamGenType'])
 
 DebugFlag('GUPSGen')
-SimObject('GUPSGen.py')
+SimObject('GUPSGen.py', sim_objects=['GUPSGen'])
 
 if env['USE_PYTHON']:
     Source('pygen.cc', add_tags='python')
-    SimObject('PyTrafficGen.py')
+    SimObject('PyTrafficGen.py', sim_objects=['PyTrafficGen'])
 
 # Only build the traffic generator if we have support for protobuf as the
 # tracing relies on it
 if env['HAVE_PROTOBUF']:
-    SimObject('TrafficGen.py')
+    SimObject('TrafficGen.py', sim_objects=['TrafficGen'])
     Source('trace_gen.cc')
     Source('traffic_gen.cc')
 
diff --git a/src/cpu/trace/SConscript b/src/cpu/trace/SConscript
index aa450b1..27d5fbe 100644
--- a/src/cpu/trace/SConscript
+++ b/src/cpu/trace/SConscript
@@ -5,7 +5,7 @@
 
 # Only build TraceCPU if we have support for protobuf as TraceCPU relies on it
 if env['HAVE_PROTOBUF']:
-    SimObject('TraceCPU.py')
+    SimObject('TraceCPU.py', sim_objects=['TraceCPU'])
     Source('trace_cpu.cc')
 
 DebugFlag('TraceCPUData')
diff --git a/src/dev/SConscript b/src/dev/SConscript
index e86e48b..db3163e 100644
--- a/src/dev/SConscript
+++ b/src/dev/SConscript
@@ -28,7 +28,8 @@
 
 Import('*')
 
-SimObject('Device.py')
+SimObject('Device.py', sim_objects=[
+    'PioDevice', 'BasicPioDevice', 'DmaDevice', 'DmaVirtDevice', 'IsaFake'])
 Source('io_device.cc')
 Source('isa_fake.cc')
 Source('dma_device.cc')
@@ -40,13 +41,13 @@
 DebugFlag('IsaFake')
 DebugFlag('DMA')
 
-SimObject('Platform.py')
+SimObject('Platform.py', sim_objects=['Platform'])
 Source('platform.cc')
 
 if env['TARGET_ISA'] == 'null':
     Return()
 
-SimObject('BadDevice.py')
+SimObject('BadDevice.py', sim_objects=['BadDevice'])
 
 Source('baddev.cc')
 Source('intel_8254_timer.cc')
diff --git a/src/dev/amdgpu/SConscript b/src/dev/amdgpu/SConscript
index eeff32e..605a0b7 100644
--- a/src/dev/amdgpu/SConscript
+++ b/src/dev/amdgpu/SConscript
@@ -35,7 +35,7 @@
     Return()
 
 # Controllers
-SimObject('AMDGPU.py', tags='x86 isa')
+SimObject('AMDGPU.py', sim_objects=['AMDGPUDevice'], tags='x86 isa')
 
 Source('amdgpu_device.cc', tags='x86 isa')
 Source('mmio_reader.cc', tags='x86 isa')
diff --git a/src/dev/arm/SConscript b/src/dev/arm/SConscript
index f2fc467..e74b190 100644
--- a/src/dev/arm/SConscript
+++ b/src/dev/arm/SConscript
@@ -37,18 +37,32 @@
 
 Import('*')
 
-SimObject('AbstractNVM.py', tags='arm isa')
-SimObject('Display.py', tags='arm isa')
-SimObject('Doorbell.py', tags='arm isa')
-SimObject('FlashDevice.py', tags='arm isa')
-SimObject('GenericTimer.py', tags='arm isa')
-SimObject('Gic.py', tags='arm isa')
-SimObject('RealView.py', tags='arm isa')
-SimObject('SMMUv3.py', tags='arm isa')
-SimObject('UFSHostDevice.py', tags='arm isa')
-SimObject('EnergyCtrl.py', tags='arm isa')
-SimObject('NoMali.py', tags='arm isa')
-SimObject('VirtIOMMIO.py', tags='arm isa')
+SimObject('AbstractNVM.py', sim_objects=['AbstractNVM'], tags='arm isa')
+SimObject('Display.py', sim_objects=['Display'], tags='arm isa')
+SimObject('Doorbell.py', sim_objects=['Doorbell'], tags='arm isa')
+SimObject('FlashDevice.py', sim_objects=['FlashDevice'],
+        enums=['DataDistribution'], tags='arm isa')
+SimObject('GenericTimer.py', sim_objects=[
+    'SystemCounter', 'GenericTimer', 'GenericTimerFrame',
+    'GenericTimerMem'], tags='arm isa')
+SimObject('Gic.py', sim_objects=[
+    'BaseGic', 'ArmInterruptPin', 'ArmSPI', 'ArmPPI', 'ArmSigInterruptPin',
+    'GicV2', 'Gicv2mFrame', 'Gicv2m', 'VGic', 'Gicv3Its', 'Gicv3'],
+    enums=['ArmInterruptType'], tags='arm isa')
+SimObject('RealView.py', sim_objects=[
+    'AmbaPioDevice', 'AmbaIntDevice', 'AmbaDmaDevice', 'A9SCU',
+    'GenericArmPciHost', 'RealViewCtrl', 'RealViewOsc',
+    'RealViewTemperatureSensor', 'AmbaFake', 'Pl011', 'Sp804', 'Sp805',
+    'GenericWatchdog', 'CpuLocalTimer', 'PL031', 'Pl050', 'Pl111', 'HDLcd',
+    'FVPBasePwrCtrl', 'RealView'],
+    enums=['ArmPciIntRouting'], tags='arm isa')
+SimObject('SMMUv3.py', sim_objects=['SMMUv3DeviceInterface', 'SMMUv3'],
+    tags='arm isa')
+SimObject('UFSHostDevice.py', sim_objects=['UFSHostDevice'], tags='arm isa')
+SimObject('EnergyCtrl.py', sim_objects=['EnergyCtrl'], tags='arm isa')
+SimObject('NoMali.py', sim_objects=['NoMaliGpu', 'CustomNoMaliGpu'],
+    enums=['NoMaliGpuType'], tags='arm isa')
+SimObject('VirtIOMMIO.py', sim_objects=['MmioVirtIO'], tags='arm isa')
 if env['USE_ARM_FASTMODEL']:
     SimObject('VExpressFastmodel.py', tags='arm isa')
 
diff --git a/src/dev/arm/css/SConscript b/src/dev/arm/css/SConscript
index b57a296..aa3c229 100644
--- a/src/dev/arm/css/SConscript
+++ b/src/dev/arm/css/SConscript
@@ -37,9 +37,12 @@
 
 Import('*')
 
-SimObject('MHU.py', tags='arm isa')
-SimObject('Scmi.py', tags='arm isa')
-SimObject('Scp.py', tags='arm isa')
+SimObject('MHU.py', sim_objects=[
+    'MhuDoorbell', 'Scp2ApDoorbell', 'Ap2ScpDoorbell', 'MHU'], tags='arm isa')
+SimObject('Scmi.py', sim_objects=[
+    'ScmiChannel', 'ScmiAgentChannel', 'ScmiPlatformChannel',
+    'ScmiCommunication', 'ScmiPlatform'], tags='arm isa')
+SimObject('Scp.py', sim_objects=['Scp'], tags='arm isa')
 
 Source('mhu.cc', tags='arm isa')
 Source('scmi_platform.cc', tags='arm isa')
diff --git a/src/dev/hsa/SConscript b/src/dev/hsa/SConscript
index 1756e7d..14bdeac 100644
--- a/src/dev/hsa/SConscript
+++ b/src/dev/hsa/SConscript
@@ -36,7 +36,7 @@
 if not env['BUILD_GPU']:
     Return()
 
-SimObject('HSADevice.py')
+SimObject('HSADevice.py', sim_objects=['HSAPacketProcessor'])
 
 Source('hsa_packet_processor.cc')
 Source('hw_scheduler.cc')
diff --git a/src/dev/i2c/SConscript b/src/dev/i2c/SConscript
index f20a6a2..71f7fce 100644
--- a/src/dev/i2c/SConscript
+++ b/src/dev/i2c/SConscript
@@ -40,5 +40,5 @@
 if env['TARGET_ISA'] == 'null':
     Return()
 
-SimObject('I2C.py')
+SimObject('I2C.py', sim_objects=['I2CDevice', 'I2CBus'])
 Source('bus.cc')
diff --git a/src/dev/lupio/SConscript b/src/dev/lupio/SConscript
index 82fb81e..01d7f9d 100644
--- a/src/dev/lupio/SConscript
+++ b/src/dev/lupio/SConscript
@@ -26,14 +26,14 @@
 
 Import('*')
 
-SimObject('LupioBLK.py', tags='riscv isa')
-SimObject('LupioIPI.py', tags='riscv isa')
-SimObject('LupioPIC.py', tags='riscv isa')
-SimObject('LupioRNG.py', tags='riscv isa')
-SimObject('LupioRTC.py', tags='riscv isa')
-SimObject('LupioTMR.py', tags='riscv isa')
-SimObject('LupioTTY.py', tags='riscv isa')
-SimObject('LupioSYS.py', tags='riscv isa')
+SimObject('LupioBLK.py', sim_objects=['LupioBLK'], tags='riscv isa')
+SimObject('LupioIPI.py', sim_objects=['LupioIPI'], tags='riscv isa')
+SimObject('LupioPIC.py', sim_objects=['LupioPIC'], tags='riscv isa')
+SimObject('LupioRNG.py', sim_objects=['LupioRNG'], tags='riscv isa')
+SimObject('LupioRTC.py', sim_objects=['LupioRTC'], tags='riscv isa')
+SimObject('LupioTMR.py', sim_objects=['LupioTMR'], tags='riscv isa')
+SimObject('LupioTTY.py', sim_objects=['LupioTTY'], tags='riscv isa')
+SimObject('LupioSYS.py', sim_objects=['LupioSYS'], tags='riscv isa')
 
 DebugFlag('LupioBLK')
 DebugFlag('LupioIPI')
diff --git a/src/dev/mips/SConscript b/src/dev/mips/SConscript
index b1250a2..10a403d 100755
--- a/src/dev/mips/SConscript
+++ b/src/dev/mips/SConscript
@@ -28,7 +28,8 @@
 
 Import('*')
 
-SimObject('Malta.py', tags='mips isa')
+SimObject('Malta.py', sim_objects=['MaltaCChip', 'MaltaIO', 'Malta'],
+    tags='mips isa')
 
 DebugFlag('Malta', tags='mips isa')
 
diff --git a/src/dev/net/SConscript b/src/dev/net/SConscript
index 31de60d..4ba68cc 100644
--- a/src/dev/net/SConscript
+++ b/src/dev/net/SConscript
@@ -40,7 +40,11 @@
 
 Import('*')
 
-SimObject('Ethernet.py')
+SimObject('Ethernet.py', sim_objects=[
+    'EtherLink', 'DistEtherLink', 'EtherBus', 'EtherSwitch', 'EtherTapBase',
+    'EtherTapStub', 'EtherDump', 'EtherDevice', 'IGbE', 'EtherDevBase',
+    'NSGigE', 'Sinic'] +
+    (['EtherTap'] if env['HAVE_TUNTAP'] else []))
 
 # Basic Ethernet infrastructure
 Source('etherbus.cc')
diff --git a/src/dev/pci/SConscript b/src/dev/pci/SConscript
index af2c190..1bfe1b6 100644
--- a/src/dev/pci/SConscript
+++ b/src/dev/pci/SConscript
@@ -40,14 +40,16 @@
 
 Import('*')
 
-SimObject('PciDevice.py')
+SimObject('PciDevice.py', sim_objects=[
+    'PciBar', 'PciBarNone', 'PciIoBar', 'PciLegacyIoBar', 'PciMemBar',
+    'PciMemUpperBar', 'PciDevice'])
 Source('device.cc')
 DebugFlag('PciDevice')
 
-SimObject('PciHost.py')
+SimObject('PciHost.py', sim_objects=['PciHost', 'GenericPciHost'])
 Source('host.cc')
 DebugFlag('PciHost')
 
-SimObject('CopyEngine.py')
+SimObject('CopyEngine.py', sim_objects=['CopyEngine'])
 Source('copy_engine.cc')
 DebugFlag('DMACopyEngine')
diff --git a/src/dev/ps2/SConscript b/src/dev/ps2/SConscript
index b6fc482..303d25f 100644
--- a/src/dev/ps2/SConscript
+++ b/src/dev/ps2/SConscript
@@ -40,7 +40,8 @@
 if env['TARGET_ISA'] == 'null':
     Return()
 
-SimObject('PS2.py')
+SimObject('PS2.py', sim_objects=[
+    'PS2Device', 'PS2Keyboard', 'PS2Mouse', 'PS2TouchKit'])
 Source('device.cc')
 Source('keyboard.cc')
 Source('mouse.cc')
diff --git a/src/dev/riscv/SConscript b/src/dev/riscv/SConscript
index 5124b55..d0ef5eb 100755
--- a/src/dev/riscv/SConscript
+++ b/src/dev/riscv/SConscript
@@ -28,13 +28,14 @@
 
 Import('*')
 
-SimObject('HiFive.py', tags='riscv isa')
-SimObject('LupV.py', tags='riscv isa')
-SimObject('Clint.py', tags='riscv isa')
-SimObject('PlicDevice.py', tags='riscv isa')
-SimObject('Plic.py', tags='riscv isa')
-SimObject('RTC.py', tags='riscv isa')
-SimObject('RiscvVirtIOMMIO.py', tags='riscv isa')
+SimObject('HiFive.py', sim_objects=['HiFive'], tags='riscv isa')
+SimObject('LupV.py', sim_objects=['LupV'], tags='riscv isa')
+SimObject('Clint.py', sim_objects=['Clint'], tags='riscv isa')
+SimObject('PlicDevice.py', sim_objects=['PlicIntDevice'], tags='riscv isa')
+SimObject('Plic.py', sim_objects=['Plic'], tags='riscv isa')
+SimObject('RTC.py', sim_objects=['RiscvRTC'], tags='riscv isa')
+SimObject('RiscvVirtIOMMIO.py', sim_objects=['RiscvMmioVirtIO'],
+    tags='riscv isa')
 
 DebugFlag('Clint', tags='riscv isa')
 DebugFlag('Plic', tags='riscv isa')
diff --git a/src/dev/serial/SConscript b/src/dev/serial/SConscript
index 309020b..1f5823d 100644
--- a/src/dev/serial/SConscript
+++ b/src/dev/serial/SConscript
@@ -43,9 +43,9 @@
 if env['TARGET_ISA'] == 'null':
     Return()
 
-SimObject('Serial.py')
-SimObject('Terminal.py')
-SimObject('Uart.py')
+SimObject('Serial.py', sim_objects=['SerialDevice', 'SerialNullDevice'])
+SimObject('Terminal.py', sim_objects=['Terminal'], enums=['TerminalDump'])
+SimObject('Uart.py', sim_objects=['Uart', 'SimpleUart', 'Uart8250'])
 
 Source('serial.cc')
 Source('simple.cc')
diff --git a/src/dev/sparc/SConscript b/src/dev/sparc/SConscript
index d61b9ea..2f758b4 100644
--- a/src/dev/sparc/SConscript
+++ b/src/dev/sparc/SConscript
@@ -28,7 +28,8 @@
 
 Import('*')
 
-SimObject('T1000.py', tags='sparc isa')
+SimObject('T1000.py', sim_objects=['MmDisk', 'DumbTOD', 'Iob', 'T1000'],
+    tags='sparc isa')
 
 Source('dtod.cc', tags='sparc isa')
 Source('iob.cc', tags='sparc isa')
diff --git a/src/dev/storage/SConscript b/src/dev/storage/SConscript
index d615435..27abf2d 100644
--- a/src/dev/storage/SConscript
+++ b/src/dev/storage/SConscript
@@ -44,7 +44,7 @@
     Return()
 
 # Controllers
-SimObject('Ide.py')
+SimObject('Ide.py', sim_objects=['IdeDisk', 'IdeController'], enums=['IdeID'])
 
 Source('ide_ctrl.cc')
 Source('ide_disk.cc')
@@ -53,8 +53,9 @@
 DebugFlag('IdeDisk')
 
 # Disk models
-SimObject('DiskImage.py')
-SimObject('SimpleDisk.py')
+SimObject('DiskImage.py', sim_objects=[
+    'DiskImage', 'RawDiskImage', 'CowDiskImage'])
+SimObject('SimpleDisk.py', sim_objects=['SimpleDisk'])
 
 Source('disk_image.cc')
 Source('simple_disk.cc')
diff --git a/src/dev/virtio/SConscript b/src/dev/virtio/SConscript
index a22f35e..bf083e7 100644
--- a/src/dev/virtio/SConscript
+++ b/src/dev/virtio/SConscript
@@ -40,10 +40,12 @@
 if env['TARGET_ISA'] == 'null':
     Return()
 
-SimObject('VirtIO.py')
-SimObject('VirtIOConsole.py')
-SimObject('VirtIOBlock.py')
-SimObject('VirtIO9P.py')
+SimObject('VirtIO.py', sim_objects=[
+    'VirtIODeviceBase', 'VirtIODummyDevice', 'PciVirtIO'])
+SimObject('VirtIOConsole.py', sim_objects=['VirtIOConsole'])
+SimObject('VirtIOBlock.py', sim_objects=['VirtIOBlock'])
+SimObject('VirtIO9P.py', sim_objects=[
+    'VirtIO9PBase', 'VirtIO9PProxy', 'VirtIO9PDiod', 'VirtIO9PSocket'])
 
 Source('base.cc')
 Source('pci.cc')
diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript
index 6bee57d..5a1c0ec 100644
--- a/src/dev/x86/SConscript
+++ b/src/dev/x86/SConscript
@@ -28,36 +28,37 @@
 
 Import('*')
 
-SimObject('Pc.py', tags='x86 isa')
+SimObject('Pc.py', sim_objects=['Pc'], tags='x86 isa')
 Source('pc.cc', tags='x86 isa')
 
-SimObject('SouthBridge.py', tags='x86 isa')
+SimObject('SouthBridge.py', sim_objects=['SouthBridge'], tags='x86 isa')
 Source('south_bridge.cc', tags='x86 isa')
 
-SimObject('Cmos.py', tags='x86 isa')
+SimObject('Cmos.py', sim_objects=['Cmos'], tags='x86 isa')
 Source('cmos.cc', tags='x86 isa')
 DebugFlag('CMOS', 'Accesses to CMOS devices', tags='x86 isa')
 
-SimObject('I8259.py', tags='x86 isa')
+SimObject('I8259.py', sim_objects=['I8259'], enums=['X86I8259CascadeMode'],
+    tags='x86 isa')
 Source('i8259.cc', tags='x86 isa')
 DebugFlag('I8259', 'Accesses to the I8259 PIC devices', tags='x86 isa')
 
-SimObject('I8254.py', tags='x86 isa')
+SimObject('I8254.py', sim_objects=['I8254'], tags='x86 isa')
 Source('i8254.cc', tags='x86 isa')
 DebugFlag('I8254', 'Interrupts from the I8254 timer', tags='x86 isa');
 
-SimObject('I8237.py', tags='x86 isa')
+SimObject('I8237.py', sim_objects=['I8237'], tags='x86 isa')
 Source('i8237.cc', tags='x86 isa')
 DebugFlag('I8237', 'The I8237 dma controller', tags='x86 isa');
 
-SimObject('I8042.py', tags='x86 isa')
+SimObject('I8042.py', sim_objects=['I8042'], tags='x86 isa')
 Source('i8042.cc', tags='x86 isa')
 DebugFlag('I8042', 'The I8042 keyboard controller', tags='x86 isa');
 
-SimObject('PcSpeaker.py', tags='x86 isa')
+SimObject('PcSpeaker.py', sim_objects=['PcSpeaker'], tags='x86 isa')
 Source('speaker.cc', tags='x86 isa')
 DebugFlag('PcSpeaker', tags='x86 isa')
 
-SimObject('I82094AA.py', tags='x86 isa')
+SimObject('I82094AA.py', sim_objects=['I82094AA'], tags='x86 isa')
 Source('i82094aa.cc', tags='x86 isa')
 DebugFlag('I82094AA', tags='x86 isa')
diff --git a/src/gpu-compute/SConscript b/src/gpu-compute/SConscript
index 2ccf1b7..e7153fa 100644
--- a/src/gpu-compute/SConscript
+++ b/src/gpu-compute/SConscript
@@ -36,9 +36,14 @@
 if not env['BUILD_GPU']:
     Return()
 
-SimObject('GPU.py')
-SimObject('GPUStaticInstFlags.py')
-SimObject('LdsState.py')
+SimObject('GPU.py', sim_objects=[
+    'PoolManager', 'SimplePoolManager', 'DynPoolManager', 'RegisterFile',
+    'ScalarRegisterFile', 'VectorRegisterFile', 'RegisterManager', 'Wavefront',
+    'ComputeUnit', 'Shader', 'GPUComputeDriver', 'GPURenderDriver',
+    'GPUDispatcher', 'GPUCommandProcessor'],
+    enums=['PrefetchType', 'GfxVersion', 'StorageClassType'])
+SimObject('GPUStaticInstFlags.py', enums=['GPUStaticInstFlags'])
+SimObject('LdsState.py', sim_objects=['LdsState'])
 
 Source('comm.cc')
 Source('compute_unit.cc')
diff --git a/src/learning_gem5/part2/SConscript b/src/learning_gem5/part2/SConscript
index c709f03..a047282 100644
--- a/src/learning_gem5/part2/SConscript
+++ b/src/learning_gem5/part2/SConscript
@@ -27,10 +27,10 @@
 
 Import('*')
 
-SimObject('SimpleObject.py')
-SimObject('HelloObject.py')
-SimObject('SimpleMemobj.py')
-SimObject('SimpleCache.py')
+SimObject('SimpleObject.py', sim_objects=['SimpleObject'])
+SimObject('HelloObject.py', sim_objects=['HelloObject', 'GoodbyeObject'])
+SimObject('SimpleMemobj.py', sim_objects=['SimpleMemobj'])
+SimObject('SimpleCache.py', sim_objects=['SimpleCache'])
 
 Source('simple_object.cc')
 Source('hello_object.cc')
diff --git a/src/mem/SConscript b/src/mem/SConscript
index ddf6fee..2fe6c8c 100644
--- a/src/mem/SConscript
+++ b/src/mem/SConscript
@@ -40,25 +40,27 @@
 
 Import('*')
 
-SimObject('CommMonitor.py')
+SimObject('CommMonitor.py', sim_objects=['CommMonitor'])
 Source('comm_monitor.cc')
 
-SimObject('AbstractMemory.py')
-SimObject('AddrMapper.py')
-SimObject('Bridge.py')
-SimObject('MemCtrl.py')
-SimObject('MemInterface.py')
-SimObject('DRAMInterface.py')
-SimObject('NVMInterface.py')
-SimObject('ExternalMaster.py')
-SimObject('ExternalSlave.py')
-SimObject('CfiMemory.py')
-SimObject('SimpleMemory.py')
-SimObject('XBar.py')
-SimObject('HMCController.py')
-SimObject('SerialLink.py')
-SimObject('MemDelay.py')
-SimObject('PortTerminator.py')
+SimObject('AbstractMemory.py', sim_objects=['AbstractMemory'])
+SimObject('AddrMapper.py', sim_objects=['AddrMapper', 'RangeAddrMapper'])
+SimObject('Bridge.py', sim_objects=['Bridge'])
+SimObject('MemCtrl.py', sim_objects=['MemCtrl'], enums=['MemSched'])
+SimObject('MemInterface.py', sim_objects=['MemInterface'], enums=['AddrMap'])
+SimObject('DRAMInterface.py', sim_objects=['DRAMInterface'],
+        enums=['PageManage'])
+SimObject('NVMInterface.py', sim_objects=['NVMInterface'])
+SimObject('ExternalMaster.py', sim_objects=['ExternalMaster'])
+SimObject('ExternalSlave.py', sim_objects=['ExternalSlave'])
+SimObject('CfiMemory.py', sim_objects=['CfiMemory'])
+SimObject('SimpleMemory.py', sim_objects=['SimpleMemory'])
+SimObject('XBar.py', sim_objects=[
+    'BaseXBar', 'NoncoherentXBar', 'CoherentXBar', 'SnoopFilter'])
+SimObject('HMCController.py', sim_objects=['HMCController'])
+SimObject('SerialLink.py', sim_objects=['SerialLink'])
+SimObject('MemDelay.py', sim_objects=['MemDelay', 'SimpleMemDelay'])
+SimObject('PortTerminator.py', sim_objects=['PortTerminator'])
 
 Source('abstract_mem.cc')
 Source('addr_mapper.cc')
@@ -96,16 +98,16 @@
     Source('page_table.cc')
 
 if env['HAVE_DRAMSIM']:
-    SimObject('DRAMSim2.py')
+    SimObject('DRAMSim2.py', sim_objects=['DRAMSim2'])
     Source('dramsim2_wrapper.cc')
     Source('dramsim2.cc')
 
 if env['HAVE_DRAMSIM3']:
-    SimObject('DRAMsim3.py')
+    SimObject('DRAMsim3.py', sim_objects=['DRAMsim3'])
     Source('dramsim3_wrapper.cc')
     Source('dramsim3.cc')
 
-SimObject('MemChecker.py')
+SimObject('MemChecker.py', sim_objects=['MemChecker', 'MemCheckerMonitor'])
 Source('mem_checker.cc')
 Source('mem_checker_monitor.cc')
 
diff --git a/src/mem/cache/SConscript b/src/mem/cache/SConscript
index 7910b93..f1bd83a 100644
--- a/src/mem/cache/SConscript
+++ b/src/mem/cache/SConscript
@@ -28,7 +28,9 @@
 
 Import('*')
 
-SimObject('Cache.py')
+SimObject('Cache.py', sim_objects=[
+    'WriteAllocator', 'BaseCache', 'Cache', 'NoncoherentCache'],
+    enums=['Clusivity'])
 
 Source('base.cc')
 Source('cache.cc')
diff --git a/src/mem/cache/compressors/SConscript b/src/mem/cache/compressors/SConscript
index ae95707..9a8fef7 100644
--- a/src/mem/cache/compressors/SConscript
+++ b/src/mem/cache/compressors/SConscript
@@ -28,7 +28,12 @@
 
 Import('*')
 
-SimObject('Compressors.py')
+SimObject('Compressors.py', sim_objects=[
+    'BaseCacheCompressor', 'BaseDictionaryCompressor',
+    'Base64Delta8', 'Base64Delta16', 'Base64Delta32',
+    'Base32Delta8', 'Base32Delta16', 'Base16Delta8',
+    'CPack', 'FPC', 'FPCD', 'FrequentValuesCompressor', 'MultiCompressor',
+    'PerfectCompressor', 'RepeatedQwordsCompressor', 'ZeroCompressor'])
 
 Source('base.cc')
 Source('base_dictionary_compressor.cc')
diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript
index 57ccb6e..8ce15e9 100644
--- a/src/mem/cache/prefetch/SConscript
+++ b/src/mem/cache/prefetch/SConscript
@@ -28,7 +28,14 @@
 
 Import('*')
 
-SimObject('Prefetcher.py')
+SimObject('Prefetcher.py', sim_objects=[
+    'BasePrefetcher', 'MultiPrefetcher', 'QueuedPrefetcher',
+    'StridePrefetcherHashedSetAssociative', 'StridePrefetcher',
+    'TaggedPrefetcher', 'IndirectMemoryPrefetcher', 'SignaturePathPrefetcher',
+    'SignaturePathPrefetcherV2', 'AccessMapPatternMatching', 'AMPMPrefetcher',
+    'DeltaCorrelatingPredictionTables', 'DCPTPrefetcher',
+    'IrregularStreamBufferPrefetcher', 'SlimAMPMPrefetcher',
+    'BOPPrefetcher', 'SBOOEPrefetcher', 'STeMSPrefetcher', 'PIFPrefetcher'])
 
 Source('access_map_pattern_matching.cc')
 Source('base.cc')
diff --git a/src/mem/cache/replacement_policies/SConscript b/src/mem/cache/replacement_policies/SConscript
index 6370052..19f987b 100644
--- a/src/mem/cache/replacement_policies/SConscript
+++ b/src/mem/cache/replacement_policies/SConscript
@@ -28,7 +28,10 @@
 
 Import('*')
 
-SimObject('ReplacementPolicies.py')
+SimObject('ReplacementPolicies.py', sim_objects=[
+    'BaseReplacementPolicy', 'DuelingRP', 'FIFORP', 'SecondChanceRP',
+    'LFURP', 'LRURP', 'BIPRP', 'MRURP', 'RandomRP', 'BRRIPRP', 'SHiPRP',
+    'SHiPMemRP', 'SHiPPCRP', 'TreePLRURP', 'WeightedLRURP'])
 
 Source('bip_rp.cc')
 Source('brrip_rp.cc')
diff --git a/src/mem/cache/tags/SConscript b/src/mem/cache/tags/SConscript
index 9c6f35d..f639be0 100644
--- a/src/mem/cache/tags/SConscript
+++ b/src/mem/cache/tags/SConscript
@@ -28,7 +28,8 @@
 
 Import('*')
 
-SimObject('Tags.py')
+SimObject('Tags.py', sim_objects=[
+    'BaseTags', 'BaseSetAssoc', 'SectorTags', 'CompressedTags', 'FALRU'])
 
 Source('base.cc')
 Source('base_set_assoc.cc')
diff --git a/src/mem/cache/tags/indexing_policies/SConscript b/src/mem/cache/tags/indexing_policies/SConscript
index 98c9202..60d8912 100644
--- a/src/mem/cache/tags/indexing_policies/SConscript
+++ b/src/mem/cache/tags/indexing_policies/SConscript
@@ -27,7 +27,8 @@
 
 Import('*')
 
-SimObject('IndexingPolicies.py')
+SimObject('IndexingPolicies.py', sim_objects=[
+    'BaseIndexingPolicy', 'SetAssociative', 'SkewedAssociative'])
 
 Source('base.cc')
 Source('set_associative.cc')
diff --git a/src/mem/probes/SConscript b/src/mem/probes/SConscript
index 25dc9ca..6df807f 100644
--- a/src/mem/probes/SConscript
+++ b/src/mem/probes/SConscript
@@ -37,16 +37,16 @@
 
 Import('*')
 
-SimObject('BaseMemProbe.py')
+SimObject('BaseMemProbe.py', sim_objects=['BaseMemProbe'])
 Source('base.cc')
 
-SimObject('StackDistProbe.py')
+SimObject('StackDistProbe.py', sim_objects=['StackDistProbe'])
 Source('stack_dist.cc')
 
-SimObject('MemFootprintProbe.py')
+SimObject('MemFootprintProbe.py', sim_objects=['MemFootprintProbe'])
 Source('mem_footprint.cc')
 
 # Packet tracing requires protobuf support
 if env['HAVE_PROTOBUF']:
-    SimObject('MemTraceProbe.py')
+    SimObject('MemTraceProbe.py', sim_objects=['MemTraceProbe'])
     Source('mem_trace.cc')
diff --git a/src/mem/qos/SConscript b/src/mem/qos/SConscript
index 1d90f9c..29c9f5b 100644
--- a/src/mem/qos/SConscript
+++ b/src/mem/qos/SConscript
@@ -35,11 +35,13 @@
 
 Import('*')
 
-SimObject('QoSMemCtrl.py')
-SimObject('QoSMemSinkCtrl.py')
-SimObject('QoSMemSinkInterface.py')
-SimObject('QoSPolicy.py')
-SimObject('QoSTurnaround.py')
+SimObject('QoSMemCtrl.py', sim_objects=['QoSMemCtrl'], enums=['QoSQPolicy'])
+SimObject('QoSMemSinkCtrl.py', sim_objects=['QoSMemSinkCtrl'])
+SimObject('QoSMemSinkInterface.py', sim_objects=['QoSMemSinkInterface'])
+SimObject('QoSPolicy.py', sim_objects=[
+    'QoSPolicy', 'QoSFixedPriorityPolicy', 'QoSPropFairPolicy'])
+SimObject('QoSTurnaround.py', sim_objects=[
+    'QoSTurnaroundPolicy', 'QoSTurnaroundPolicyIdeal'])
 
 Source('policy.cc')
 Source('policy_fixed_prio.cc')
diff --git a/src/mem/ruby/network/SConscript b/src/mem/ruby/network/SConscript
index 1e96535..a1ea977 100644
--- a/src/mem/ruby/network/SConscript
+++ b/src/mem/ruby/network/SConscript
@@ -31,10 +31,12 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('BasicLink.py')
-SimObject('BasicRouter.py')
-SimObject('MessageBuffer.py')
-SimObject('Network.py')
+SimObject('BasicLink.py', sim_objects=[
+    'BasicLink', 'BasicExtLink', 'BasicIntLink'])
+SimObject('BasicRouter.py', sim_objects=['BasicRouter'])
+SimObject('MessageBuffer.py', sim_objects=['MessageBuffer'],
+        enums=['MessageRandomization'])
+SimObject('Network.py', sim_objects=['RubyNetwork'])
 
 Source('BasicLink.cc')
 Source('BasicRouter.cc')
diff --git a/src/mem/ruby/network/fault_model/SConscript b/src/mem/ruby/network/fault_model/SConscript
index ee96d84..3aff28e 100644
--- a/src/mem/ruby/network/fault_model/SConscript
+++ b/src/mem/ruby/network/fault_model/SConscript
@@ -36,6 +36,6 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('FaultModel.py')
+SimObject('FaultModel.py', sim_objects=['FaultModel'])
 Source('FaultModel.cc')
 
diff --git a/src/mem/ruby/network/garnet/SConscript b/src/mem/ruby/network/garnet/SConscript
index e3bc110..af6e758 100644
--- a/src/mem/ruby/network/garnet/SConscript
+++ b/src/mem/ruby/network/garnet/SConscript
@@ -31,8 +31,11 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('GarnetLink.py')
-SimObject('GarnetNetwork.py')
+SimObject('GarnetLink.py', enums=['CDCType'], sim_objects=[
+    'NetworkLink', 'CreditLink', 'NetworkBridge', 'GarnetIntLink',
+    'GarnetExtLink'])
+SimObject('GarnetNetwork.py', sim_objects=[
+    'GarnetNetwork', 'GarnetNetworkInterface', 'GarnetRouter'])
 
 Source('GarnetLink.cc')
 Source('GarnetNetwork.cc')
diff --git a/src/mem/ruby/network/simple/SConscript b/src/mem/ruby/network/simple/SConscript
index 8cbbbac..32c5082 100644
--- a/src/mem/ruby/network/simple/SConscript
+++ b/src/mem/ruby/network/simple/SConscript
@@ -31,8 +31,8 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('SimpleLink.py')
-SimObject('SimpleNetwork.py')
+SimObject('SimpleLink.py', sim_objects=['SimpleExtLink', 'SimpleIntLink'])
+SimObject('SimpleNetwork.py', sim_objects=['SimpleNetwork', 'Switch'])
 
 Source('PerfectSwitch.cc')
 Source('SimpleLink.cc')
diff --git a/src/mem/ruby/protocol/SConscript b/src/mem/ruby/protocol/SConscript
index 6966489..f137021 100644
--- a/src/mem/ruby/protocol/SConscript
+++ b/src/mem/ruby/protocol/SConscript
@@ -26,12 +26,10 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-import os
+import os.path
 import re
 import sys
 
-from os.path import isdir, isfile, join as joinpath
-
 from SCons.Scanner import Classic
 
 from gem5_scons import Transform
@@ -52,7 +50,7 @@
 for root,dirs,files in os.walk(slicc_dir.srcnode().abspath):
     for f in files:
         if f.endswith('.py'):
-            slicc_depends.append(File(joinpath(root, f)))
+            slicc_depends.append(File(os.path.join(root, f)))
 
 #
 # Use SLICC
@@ -113,5 +111,9 @@
     if s.endswith('.cc'):
         Source(f, append=append)
     elif s.endswith('.py'):
-        SimObject(f)
+        filename = os.path.basename(s)
+        # We currently only expect ${ident}_Controller.py to be generated, and
+        # for it to contain a single SimObject with the same name.
+        assert(filename.endswith('_Controller.py'))
+        SimObject(f, sim_objects=[os.path.splitext(filename)[0]])
 
diff --git a/src/mem/ruby/slicc_interface/SConscript b/src/mem/ruby/slicc_interface/SConscript
index 026c550..612af3a 100644
--- a/src/mem/ruby/slicc_interface/SConscript
+++ b/src/mem/ruby/slicc_interface/SConscript
@@ -31,7 +31,7 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('Controller.py')
+SimObject('Controller.py', sim_objects=['RubyController'])
 
 Source('AbstractController.cc')
 Source('AbstractCacheEntry.cc')
diff --git a/src/mem/ruby/structures/SConscript b/src/mem/ruby/structures/SConscript
index 546326b..086406d 100644
--- a/src/mem/ruby/structures/SConscript
+++ b/src/mem/ruby/structures/SConscript
@@ -31,10 +31,10 @@
 if env['PROTOCOL'] == 'None':
     Return()
 
-SimObject('RubyCache.py')
-SimObject('DirectoryMemory.py')
-SimObject('RubyPrefetcher.py')
-SimObject('WireBuffer.py')
+SimObject('RubyCache.py', sim_objects=['RubyCache'])
+SimObject('DirectoryMemory.py', sim_objects=['RubyDirectoryMemory'])
+SimObject('RubyPrefetcher.py', sim_objects=['RubyPrefetcher'])
+SimObject('WireBuffer.py', sim_objects=['RubyWireBuffer'])
 
 Source('DirectoryMemory.cc')
 Source('CacheMemory.cc')
diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript
index f93687f..2b4a804 100644
--- a/src/mem/ruby/system/SConscript
+++ b/src/mem/ruby/system/SConscript
@@ -49,11 +49,13 @@
     env.Append(CPPDEFINES=['PARTIAL_FUNC_READS'])
 
 if env['BUILD_GPU']:
-    SimObject('GPUCoalescer.py')
-SimObject('RubySystem.py')
-SimObject('Sequencer.py')
+    SimObject('GPUCoalescer.py', sim_objects=['RubyGPUCoalescer'])
+SimObject('RubySystem.py', sim_objects=['RubySystem'])
+SimObject('Sequencer.py', sim_objects=[
+    'RubyPort', 'RubyPortProxy', 'RubySequencer', 'RubyHTMSequencer',
+    'DMASequencer'])
 if env['BUILD_GPU']:
-    SimObject('VIPERCoalescer.py')
+    SimObject('VIPERCoalescer.py', sim_objects=['VIPERCoalescer'])
 
 Source('CacheRecorder.cc')
 Source('DMASequencer.cc')
diff --git a/src/sim/SConscript b/src/sim/SConscript
index 449ded8..8bf5f5d 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -28,18 +28,20 @@
 
 Import('*')
 
-SimObject('ClockedObject.py')
-SimObject('TickedObject.py')
-SimObject('Workload.py')
-SimObject('Root.py')
-SimObject('ClockDomain.py')
-SimObject('VoltageDomain.py')
-SimObject('System.py')
-SimObject('DVFSHandler.py')
-SimObject('SubSystem.py')
-SimObject('RedirectPath.py')
-SimObject('PowerState.py')
-SimObject('PowerDomain.py')
+SimObject('ClockedObject.py', sim_objects=['ClockedObject'])
+SimObject('TickedObject.py', sim_objects=['TickedObject'])
+SimObject('Workload.py', sim_objects=[
+    'Workload', 'StubWorkload', 'KernelWorkload', 'SEWorkload'])
+SimObject('Root.py', sim_objects=['Root'])
+SimObject('ClockDomain.py', sim_objects=[
+    'ClockDomain', 'SrcClockDomain', 'DerivedClockDomain'])
+SimObject('VoltageDomain.py', sim_objects=['VoltageDomain'])
+SimObject('System.py', sim_objects=['System'], enums=['MemoryMode'])
+SimObject('DVFSHandler.py', sim_objects=['DVFSHandler'])
+SimObject('SubSystem.py', sim_objects=['SubSystem'])
+SimObject('RedirectPath.py', sim_objects=['RedirectPath'])
+SimObject('PowerState.py', sim_objects=['PowerState'], enums=['PwrState'])
+SimObject('PowerDomain.py', sim_objects=['PowerDomain'])
 
 Source('async.cc')
 Source('backtrace_%s.cc' % env['BACKTRACE_IMPL'], add_tags='gem5 trace')
@@ -97,8 +99,8 @@
 GTest('serialize_handlers.test', 'serialize_handlers.test.cc')
 
 if env['TARGET_ISA'] != 'null':
-    SimObject('InstTracer.py')
-    SimObject('Process.py')
+    SimObject('InstTracer.py', sim_objects=['InstTracer'])
+    SimObject('Process.py', sim_objects=['Process', 'EmulatedDriver'])
     Source('faults.cc')
     Source('process.cc')
     Source('fd_array.cc')
diff --git a/src/sim/power/SConscript b/src/sim/power/SConscript
index 1250d13..487608d 100644
--- a/src/sim/power/SConscript
+++ b/src/sim/power/SConscript
@@ -28,11 +28,13 @@
 
 Import('*')
 
-SimObject('MathExprPowerModel.py')
-SimObject('PowerModel.py')
-SimObject('PowerModelState.py')
-SimObject('ThermalDomain.py')
-SimObject('ThermalModel.py')
+SimObject('MathExprPowerModel.py', sim_objects=['MathExprPowerModel'])
+SimObject('PowerModel.py', sim_objects=['PowerModel'], enums=['PMType'])
+SimObject('PowerModelState.py', sim_objects=['PowerModelState'])
+SimObject('ThermalDomain.py', sim_objects=['ThermalDomain'])
+SimObject('ThermalModel.py', sim_objects=[
+    'ThermalNode', 'ThermalResistor', 'ThermalCapacitor',
+    'ThermalReference', 'ThermalModel'])
 
 Source('power_model.cc')
 Source('mathexpr_powermodel.cc')
diff --git a/src/sim/probe/SConscript b/src/sim/probe/SConscript
index 8123e4e..719ab41 100644
--- a/src/sim/probe/SConscript
+++ b/src/sim/probe/SConscript
@@ -37,6 +37,6 @@
 
 Import('*')
 
-SimObject('Probe.py')
+SimObject('Probe.py', sim_objects=['ProbeListenerObject'])
 Source('probe.cc')
 DebugFlag('ProbeVerbose')
diff --git a/src/sst/SConscript b/src/sst/SConscript
index a6dec52..1c1c4fd 100644
--- a/src/sst/SConscript
+++ b/src/sst/SConscript
@@ -26,7 +26,7 @@
 
 Import('*')
 
-SimObject('OutgoingRequestBridge.py')
+SimObject('OutgoingRequestBridge.py', sim_objects=['OutgoingRequestBridge'])
 
 Source('outgoing_request_bridge.cc')
-Source('sst_responder_interface.cc')
\ No newline at end of file
+Source('sst_responder_interface.cc')
diff --git a/src/systemc/core/SConscript b/src/systemc/core/SConscript
index 662aeca..8805e9b 100644
--- a/src/systemc/core/SConscript
+++ b/src/systemc/core/SConscript
@@ -28,7 +28,8 @@
 Import('*')
 
 if env['USE_SYSTEMC']:
-    SimObject('SystemC.py')
+    SimObject('SystemC.py', sim_objects=[
+        'SystemC_Kernel', 'SystemC_ScObject', 'SystemC_ScModule'])
 
     Source('channel.cc')
     Source('event.cc')
diff --git a/src/systemc/tlm_bridge/SConscript b/src/systemc/tlm_bridge/SConscript
index 4064d09..7aba370 100644
--- a/src/systemc/tlm_bridge/SConscript
+++ b/src/systemc/tlm_bridge/SConscript
@@ -28,7 +28,10 @@
 if not env['USE_SYSTEMC']:
     Return()
 
-SimObject('TlmBridge.py')
+SimObject('TlmBridge.py', sim_objects=[
+    'Gem5ToTlmBridgeBase', 'TlmToGem5BridgeBase'] +
+    [f'Gem5ToTlmBridge{bits}' for bits in (32, 64, 128, 256, 512)] +
+    [f'TlmToGem5Bridge{bits}' for bits in (32, 64, 128, 256, 512)])
 
 Source('gem5_to_tlm.cc')
 Source('sc_ext.cc')