Also that (like the other mechanisms) means that there can be at most one
C++ class for a given Params class. It would be impossible to have
FooParams -> SimObj and BarParams -> SimObj since there is only room for
one Params in a class.

That said, we could turn the FooParams and BarParams into Params::Foo and
Params::Bar. That would be fairly trivial, and would mean we'd only have
one name to dodge, Params, although that's an easier name to collide with
accidentally.

I think a step in the right direction would be to start putting all our
gem5 stuff into a gem5 namespace. Namespaces are easy to fold away in
context (using, opening the namespace and working within it), and then we
would only have to worry about internal collisions which I think are a lot
easier to manage.

We could even start doing that now without breaking compatibility by
putting things in a gem5 namespace and then putting a "using namespace
::gem5;" at the end to maintain compatibility until we decide to switch.

Gabe

On Thu, Oct 22, 2020 at 7:50 PM Gabe Black <gabe.bl...@gmail.com> wrote:

> That would work, but we don't have includes in the middle of a class like
> that anywhere else in gem5 (that I can remember at least), which I think is
> for the best :-).
>
> Gabe
>
> On Thu, Oct 22, 2020 at 6:28 PM Gambord, Ryan via gem5-dev <
> gem5-dev@gem5.org> wrote:
>
>> @Gabe Black <gabebl...@google.com>
>> Here is an example of what this looks like. It requires slightly
>> modifying the boilerplate code generated for params structs, and then
>> moving the include from the top of the source file to inside the class.
>> This brings the struct into the class namespace.
>>
>> This should work fine as long as pybind can work with a FQN of an object.
>>
>> MySimObject.hh
>> #ifndef __MYSIMOBJECT_HH__
>> #define __MYSIMOBJECT_HH__
>>
>> class MySimObject
>> {
>>   public:
>>     #include "MySimObjectParams.hh"
>>
>>   public:
>>     MySimObject(Params * p) : myint(p->myint) {}
>>
>>     int & myInt() { return myint; }
>>
>>   private:
>>     int myint;
>> };
>> #endif // __MYSIMOBJECT_HH__
>>
>> MySimObjectParams.hh
>> // Generated automatically by SCons //
>>
>> struct Params {
>>   int myint;
>> };
>>
>> main.cc
>> #include <iostream>
>> #include <cstdlib>
>>
>> #include "MySimObject.hh"
>>
>> int
>> main( int argc, char *argv[]){
>>   MySimObject::Params p;
>>   p.myint = 5;
>>   MySimObject my_so_instance(&p);
>>   std::cout << my_so_instance.myInt() << std::endl;
>>   return EXIT_SUCCESS;
>> }
>>
>> Ryan Gambord
>> <gambo...@oregonstate.edu>
>>
>>
>>
>> On Thu, Oct 22, 2020 at 5:20 PM Gabe Black via gem5-dev <
>> gem5-dev@gem5.org> wrote:
>>
>>> [This email originated from outside of OSU. Use caution with links and
>>> attachments.]
>>> I definitely agree that we need to use more namespaces and be better
>>> citizens in the global namespace.
>>>
>>> See https://gem5.atlassian.net/browse/GEM5-730
>>>
>>> Mechanically, I don't think we can define something like
>>> Mem::Ruby::Network::BasicLink::Params since that would require adding a
>>> Params type to the not yet defined BasicLink class. You can do that with
>>> namespaces, but not with classes. We also couldn't add a params function to
>>> the SimObject for the same reason. Python doesn't define the SimObject
>>> class at all, even though it might look like it does because the python
>>> objects and C++ objects often (but not always) share the same name. The
>>> Python objects actually are the Params structs in C++, and then python uses
>>> the create method to make the actual SimObjects. The real C++ SimObject
>>> classes have no python analogue, although python has pointers to them and
>>> can indirectly call methods on them once they've been instantiated. That's
>>> how callbacks like init(), startup(), etc are handled.
>>>
>>> Gabe
>>>
>>> On Thu, Oct 22, 2020 at 10:25 AM Gambord, Ryan via gem5-dev <
>>> gem5-dev@gem5.org> wrote:
>>>
>>>> While we're thinking about the params implementations, I'd also like to
>>>> propose that we stop cluttering the global namespace with collision-prone
>>>> names:
>>>>
>>>> src/.../.../MySimObject.hh
>>>> namespace NoClutter {
>>>> class MySimObject : ::SimObject
>>>> {
>>>>     #include params/MySimObject.hh
>>>> };
>>>> };
>>>>
>>>> params/MySimObject.hh
>>>> // ... //
>>>> struct Params {
>>>> // ... //
>>>> };
>>>>
>>>> For example, ruby claimed the name "BasicLink", which is pretty
>>>> generic. Would be much better if we started moving towards
>>>> Mem::Ruby::Network::BasicLink::Params, which would be more idiomatic C++.
>>>> The params/xxx.hh sources could even include the boilerplate params()
>>>> method into the simobject class if you want. There is *the* canonical
>>>> use-case for mid-file includes -- when we have compile-time generated
>>>> boilerplate in separate sources.
>>>>
>>>> Right now, gem5 gives me "C with classes" vibes.
>>>>
>>>> Ryan Gambord
>>>> <gambo...@oregonstate.edu>
>>>>
>>>>
>>>>
>>>> On Thu, Oct 22, 2020 at 9:18 AM Jason Lowe-Power via gem5-dev <
>>>> gem5-dev@gem5.org> wrote:
>>>>
>>>>> [This email originated from outside of OSU. Use caution with links and
>>>>> attachments.]
>>>>> Another simple proposal:
>>>>> - Remove params() from the API (with deprecation)
>>>>> - Update objects that can easily be updated and remove the params()
>>>>> calls/casts. I think this is most cases of the params use outside of the
>>>>> constructor.
>>>>> - Don't worry about the others that use the params() function in many
>>>>> places that require deeper updates
>>>>> - Update the documentation to say that the "best practice" is to not
>>>>> use the param function
>>>>> - In the future, make sure that new objects don't store the params
>>>>> object.
>>>>>
>>>>> Cheers,
>>>>> Jason
>>>>>
>>>>> On Thu, Oct 22, 2020 at 8:51 AM Giacomo Travaglini <
>>>>> giacomo.travagl...@arm.com> wrote:
>>>>>
>>>>>> Let me add to the plate a simple proposal though still a bit verbose
>>>>>> and probably not that different from a manual cast
>>>>>>
>>>>>>
>>>>>>
>>>>>> Defining a template method in SimObject:
>>>>>>
>>>>>>
>>>>>>
>>>>>> *template <class Obj>*
>>>>>>
>>>>>> *Obj params()*
>>>>>>
>>>>>>
>>>>>> *{     return static_cast<Obj>(_params);*
>>>>>>
>>>>>> *    Or more secure:*
>>>>>>
>>>>>> *    param =  dynamic_cast<Obj>(_params);*
>>>>>>
>>>>>> *    assert(param);*
>>>>>>
>>>>>> *    return param;*
>>>>>>
>>>>>> *}*
>>>>>>
>>>>>>
>>>>>>
>>>>>> And delegate the type specification on the client side:
>>>>>>
>>>>>>
>>>>>>
>>>>>> For example in my shiny new
>>>>>>
>>>>>>
>>>>>>
>>>>>> Class MyObject : public SimObject {}
>>>>>>
>>>>>>
>>>>>>
>>>>>> I would use
>>>>>>
>>>>>>
>>>>>>
>>>>>> auto p = params<MyObjectParams*>();
>>>>>>
>>>>>>
>>>>>>
>>>>>> You still have to type your param type so that doesn’t make it the
>>>>>> best but I believe it’s the simplest one
>>>>>>
>>>>>>
>>>>>>
>>>>>> Giacomo
>>>>>>
>>>>>>
>>>>>>
>>>>>> *From:* Jason Lowe-Power via gem5-dev <gem5-dev@gem5.org>
>>>>>> *Sent:* 22 October 2020 16:26
>>>>>> *To:* gem5 Developer List <gem5-dev@gem5.org>
>>>>>> *Cc:* Gabe Black <gabe.bl...@gmail.com>; Jason Lowe-Power <
>>>>>> ja...@lowepower.com>
>>>>>> *Subject:* [gem5-dev] Re: SimObject params() method
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hey Gabe,
>>>>>>
>>>>>>
>>>>>>
>>>>>> Thanks for bringing this up. I have also been bothered by the lack of
>>>>>> consistency with how params are used. I can't think of an example of when
>>>>>> you need to store the params object. I would be all for getting rid of 
>>>>>> the
>>>>>> params() function and updating the documentation to say that it's best
>>>>>> practice to *not* save the params struct after the constructor. If some
>>>>>> object had a good reason to go against this best practice, that would be
>>>>>> OK, and we wouldn't need to enforce any specific design or pattern on 
>>>>>> these
>>>>>> exceptions. I would prefer to remove the params() function than add more
>>>>>> template magic.
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Thu, Oct 22, 2020 at 1:18 AM Gabe Black via gem5-dev <
>>>>>> gem5-dev@gem5.org> wrote:
>>>>>>
>>>>>> Hi folks. I'm looking at the SimObject header, and I see a few things
>>>>>> in there which are marked as part of the API and maybe shouldn't be.
>>>>>> Specifically I'm talking about the Params typedef, and the params() 
>>>>>> method.
>>>>>> There is also the _params member variable which I can see being a part of
>>>>>> the API since it can be used by other classes to make their own params()
>>>>>> function (more on that below), but the Params typedef is more or less an
>>>>>> implementation detail, and the params() method is essentially worthless
>>>>>> because it returns a SimObjectParams which doesn't have anything except 
>>>>>> the
>>>>>> object's name in it, and you can already get that with the name() method.
>>>>>>
>>>>>>
>>>>>>
>>>>>> I agree. I think the typedef is useless and shouldn't be in the API.
>>>>>> It's unfortunate that the API proposals didn't get more reviews. I think
>>>>>> it's probably OK to just drop that from the API, but the params() 
>>>>>> function
>>>>>> itself is going to need to be deprecated.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> *Params pattern*
>>>>>>
>>>>>>
>>>>>>
>>>>>> This gets to the whole Params params() pattern which is sporadically
>>>>>> implemented in some SimObjects in gem5. This pattern is that a given
>>>>>> SimObject subclass will define a Params typedef which corresponds to its
>>>>>> Params struct type, and then also define a params() method which returns
>>>>>> the _params from SimObject cast up to that type.
>>>>>>
>>>>>>
>>>>>>
>>>>>> The Params typedef itself primarily makes the definition of the
>>>>>> constructor a little more legible, since the 
>>>>>> FullFooTypeForTheArmISAParams
>>>>>> can be really verbose.
>>>>>>
>>>>>>
>>>>>>
>>>>>> I think verbose is fine. I would vote to abolish all params typedefs.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Storing the params struct itself could theoretically serve the
>>>>>> purpose of having a bunch of parameters and not having to create a member
>>>>>> variable for each one, spend a bunch of text copying values over in the
>>>>>> constructor, etc. I think most of the time this is unnecessary, but if an
>>>>>> object has tons of values in it for some reason this could make sense.
>>>>>>
>>>>>>
>>>>>>
>>>>>> I don't think there are any examples of this in the codebase. I think
>>>>>> in all cases the params data is copied into member variables. If there 
>>>>>> are
>>>>>> cases where data isn't copied, I doubt it was with a strong reason in 
>>>>>> mind.
>>>>>> The one exception to this might be Ruby, but it's an exception for all 
>>>>>> the
>>>>>> wrong reasons ;).
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> The params() method then makes the _params member available with the
>>>>>> appropriate type, so that all the FooParams members are accessible. It 
>>>>>> also
>>>>>> makes the params struct accessible outside the object which is used in a
>>>>>> place or two to read parameters without there needing to be a member in 
>>>>>> the
>>>>>> object, and probably some sort of accessor to read it.
>>>>>>
>>>>>>
>>>>>>
>>>>>> There are two main problems with this system. First, when used, it
>>>>>> adds a small but not trivial amount of boilerplate to any given class.
>>>>>> Second, it's very sporadically implemented. I think in a lot of places 
>>>>>> it's
>>>>>> there just because people aren't sure what it's for or if they need it, 
>>>>>> so
>>>>>> they just put one there regardless. I think I've done that in the past.
>>>>>>
>>>>>>
>>>>>>
>>>>>> *Alternative*
>>>>>>
>>>>>>
>>>>>>
>>>>>> The existence of the Params type and the params() method could be
>>>>>> partially eliminated by defining a templated params() method which took a
>>>>>> SimObject reference and/or pointer as its first parameter. It could then
>>>>>> figure out what Params struct went with that SimObject type using
>>>>>> typedef/template magic set up by the Params building code, and then 
>>>>>> perform
>>>>>> the appropriate cast.
>>>>>>
>>>>>>
>>>>>>
>>>>>> This has three downsides, two minor and one more serious. The minor
>>>>>> one is that when a class uses this method internally, it would have to do
>>>>>> something like params(this) instead of just params(). That's a fairly 
>>>>>> minor
>>>>>> difference and not that big a deal. For external consumers that would be
>>>>>> less of a problem since it would change from foo->params() to 
>>>>>> params(foo).
>>>>>>
>>>>>>
>>>>>>
>>>>>> The second minor issue is that the name params() is very short, and
>>>>>> likely to collide with other names. We could define that with SimObject 
>>>>>> as
>>>>>> a static method, but then that would make foo->params() turn into the 
>>>>>> more
>>>>>> verbose SimObject::params(foo), or (and I haven't checked if this is 
>>>>>> legal
>>>>>> syntax) the more odd looking foo->params(foo). The params() class can't 
>>>>>> be
>>>>>> a non-static method, because then the type of "this" would be fixed by
>>>>>> where it was defined, meaning it would not cast _params to the right 
>>>>>> type.
>>>>>> I was not able to find any mechanism in c++ that would let you treat 
>>>>>> "this"
>>>>>> as an argument for template type resolution.
>>>>>>
>>>>>>
>>>>>>
>>>>>> The third more serious problem is that this implicitly breaks the
>>>>>> ability to use two different SimObject types in python to represent the
>>>>>> same SimObject type in C++. I don't know if this happens in practice, and
>>>>>> it's also broken by the original Params pattern, since there can be only
>>>>>> one typedef in a given class. Since Params is applied adhoc manually,
>>>>>> something that is generally not good, it actually avoids this problem by
>>>>>> just not existing anywhere that would break that assumption.
>>>>>>
>>>>>>
>>>>>>
>>>>>> *Other option*
>>>>>>
>>>>>>
>>>>>>
>>>>>> Another option would be to have a templated class which would define
>>>>>> a Params type and a params() method, and inherit that into each SimObject
>>>>>> which wants to have those members. It would itself inherit from its
>>>>>> parameter which would keep the inheritance hierarchy intact, and make it
>>>>>> possible to override Params and params from super classes:
>>>>>>
>>>>>>
>>>>>>
>>>>>> FooObject : public ParamsMembers<SimObject>
>>>>>>
>>>>>>
>>>>>>
>>>>>> This has a similar problem to the above if exactly what Params type
>>>>>> to use is automatic, although here it could be an additional template
>>>>>> argument. This also trades some boilerplate for less boilerplate, has to 
>>>>>> be
>>>>>> applied manually to any classes that want to take advantage of it, and
>>>>>> obfuscates the definition of those classes.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Gabe
>>>>>>
>>>>>> _______________________________________________
>>>>>> gem5-dev mailing list -- gem5-dev@gem5.org
>>>>>> To unsubscribe send an email to gem5-dev-le...@gem5.org
>>>>>> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
>>>>>>
>>>>>> IMPORTANT NOTICE: The contents of this email and any attachments are
>>>>>> confidential and may also be privileged. If you are not the intended
>>>>>> recipient, please notify the sender immediately and do not disclose the
>>>>>> contents to any other person, use it for any purpose, or store or copy 
>>>>>> the
>>>>>> information in any medium. Thank you.
>>>>>>
>>>>> _______________________________________________
>>>>> gem5-dev mailing list -- gem5-dev@gem5.org
>>>>> To unsubscribe send an email to gem5-dev-le...@gem5.org
>>>>> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
>>>>
>>>> _______________________________________________
>>>> gem5-dev mailing list -- gem5-dev@gem5.org
>>>> To unsubscribe send an email to gem5-dev-le...@gem5.org
>>>> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
>>>
>>> _______________________________________________
>>> gem5-dev mailing list -- gem5-dev@gem5.org
>>> To unsubscribe send an email to gem5-dev-le...@gem5.org
>>> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
>>
>> _______________________________________________
>> gem5-dev mailing list -- gem5-dev@gem5.org
>> To unsubscribe send an email to gem5-dev-le...@gem5.org
>> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
>
>
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to