So we've got a bit of a muddle with initialization, and I'm looking for advice on how best to clean it up.
RIght now we have the following phases for initializing SimObjects: 1. user script calls instantiate() a. call constructors b. connect ports c. call init() 2. user script optionally calls restoreCheckpoint() a. call unserialize() 3. user script calls simulate() for the first time a. call startup() The problem is that there's some initialization that doesn't fit this model well. The two similar cases I see are in Process and X86System, where you have a set of threads assigned to the process/system, and you need to identify one of them as the main thread and set it up to run/boot, knowing that the other threads will get initialized later by that main thread. Right now this initialization happens in startup(). Unfortunately that means that if you're not careful (as is currently the case with X86System), you can clobber the state that you restored in unserialize(). The Process hierarchy avoids this problem by setting a flag in unserialize() to remember that the state was restored, and then skipping most of startup() if the flag is set. However this is ad hoc (the flag only exists in Process), the code to check the flag and skip setup() is replicated in each of the ISA-specific Process derivatives (since it has to come before any ISA-specific initialization), and obviously as the X86System case shows this makes it very easy to get confused (in fact once I figured out the problem with X86System it took a while to track down why it was that Process didn't have this same problem). Moving this initialization up into init() doesn't work directly, since it has to happen after the System/Process object knows which threads are assigned to it, but this relationship itself gets set up in the init() phase, where BaseCPU::init() calls registerThreadContexts() on the System/Process object. I can think of several possible fixes: 1. Replicate the Process hack using the checkpointRestored flag in X86System. Two variants: a. Just do another one-off hack in System. b. Add a checkpointRestored flag to SimObject so every object has one automatically. 2. Try to push registerThreadContexts() up into the BaseCPU constructor, so the initialization code in question can be moved to init(). I'm not 100% sure this will work, though I can't prove it won't. However, it seems fragile even if it does. Also it means a lot of redundant setup will be done in the cases where we do ovewrwrite the state with a restored checkpoint, which may or may not be a concern. 3. Add a phase to the initialization process to make this cleaner. Possibilities: a. Add a second-stage init() call in step 1d so that we can keep the code in question occurring after the current init(), but move it before the checkpoint restore. b. Add a new call in step 3 before startup() that's only called on objects that don't get unserialized (this is basically an even-more-first-class variant of solution 1b above, since it moves the checking of checkpointRestored up into SimObject as well). Now that I've typed these options out and looked at them, I'm leaning toward 3b. Any comments? Other ideas? Preferences for a different option? On a more mundane note, I'd like to take the opportunity to get rid of the StartupCallback class and integrate that code in SimObject, since that's the only class that derives from it now. (I think it was split out to support the old defunct ParamContext class.) Having everything in SimObject makes the process clearer. Steve _______________________________________________ m5-dev mailing list [email protected] http://m5sim.org/mailman/listinfo/m5-dev
