[ Pobierz całość w formacie PDF ]
.Code Listing 16 shows an example of a method socket.Itshows a struct that is used to model an ALU operation andprovides a method called calculate(), which the verifica-tion environment calls to get the result of a particular oper-ation.Although the verification environment (well, at leastthe ALU model) knows that there are models of differentALU operations and it can call calculate() to get the resultfor a particular operation, it doesn t actually know whichoperations are supported by the ALU.20You ll soon notice that a socket looks suspiciously similar to a hook.They are really the same thing, but I use socket to show that the intent is to cre-ate pluggable code.A hook allows the user to add functionality if they wantto, but a socket mandates a plug.Also, a socket can be a handle to a base class,whereas a hook in AOP is seldom done this way (why bother?).118 5 Creating Pluggable Codetype operation_t : [];unit alu_model_u{// "current_operation" is used as a// determinant.// Each operation extends this class and// provides a body for calculate().//current_operation: operation_t;calculate(a: int, b: int): int is undefi ned;};// Add a new operation to the model//extend operation_t : [ADD];extend ADD alu_model_u{calculate(a: int, b: int): int is{result = a + b;};};// Add a new operation to the model//extend operation_t : [MUL];extend MUL alu_model_u{calculate(a: int, b: int): int is{result = a * b;};};Code Listing 16.An example of a method socket.If the socket is a handle to a base class (a class socket),then the pluggable code will be a concrete version of theclass (either like- or when-inherited from the base class),and the concrete classes will have to provide an implemen-tation for the methods that the verification environmentwill call.5 Creating Pluggable Code 119The following code shows an example of a class socket.Infact, it is just a slight variation on the previous example.There, the new operations are added directly to the ALUmodel using when-inheritance.The operations are modeledas separate classes, and the model just contains a handle tothe active operation.type operation_t : [];unit alu_model_u{// "current_operation" is NOT used as a// determinant.Instead, it is a handle to// a base class that provides a calculation// result.To model new operations, create a// concrete class for the operation,// instantiate it, and set current_operation// equal to it.//current_operation: alu_operation_s;get_result(a: int, b: int): int is{result = current_operation.calculate(a, b);};};struct alu_operation_s{kind: operation_t;calculate(a: int, b: int): int is undefi ned;};// Create a new operation for the model//extend operation_t : [ADD];extend ADD alu_operation{calculate(a: int, b: int): int is{result = a + b;};};120 5 Creating Pluggable Code// Create a new operation for the model//extend operation_t : [MUL];extend MUL alu_operation{calculate(a: int, b: int): int is{result = a * b;};};If the verification environment can interact with the plug-gable feature, then you ll need to consider if the verifica-tion environment can select which variation to use.If youcan only have one variation included in a simulation run,then you can initialize the socket manually by including thecorrect files at compile time.If the socket is a method call,then this is the only approach that you can use.If the plug-gable feature can be selected at runtime, then you ll needto use some code to initialize the socket correctly.Thisrequires a factory, and I ll tell you about that soon.Beforethat, though, it s worth getting to know the extendable casestatement.5.1 The extendable case statementPluggable code is a great thing, but it relies on being able tononintrusively add or remove code from the verification envi-ronment.Conditional statements, such as case statements orif-then-else statements, can cause problems with this becausetheir branches tend to be hardwired, stopping you from plug-ging and unplugging features.If you unplug feature Foo, thenyou need to remove any conditional branches that select fea-ture Foo.If you want to plug in feature Bar, then you ll need toadd conditional branches to deal with Bar.For case statement5 Creating Pluggable Code 121this can be done in AOP and OOP21 with some forethought.Unfortunately, this approach cannot replace an if-then-elsestatement.These have an execution priority, and as I dis-cussed in Controlling the order of method extension callson page 65, it is very difficult to control the order in which isalso extensions are called.The obvious solution to this problem is to create a casestatement that has dynamic branches.Dynamic branchesmight sound complex, but in reality, they are simply hooks.In fact, each dynamic case statement consists of some infra-structure, one hook, and a number of user-supplied imple-mentations of the hook.Each implementation is a dynamicbranch.To create a dynamic case statement, simply define amethod that you call where you would have the case state-ment, and inside this method call an (initially) empty hookmethod.For each branch of the case statement, add an isalso advice to the hook method
[ Pobierz całość w formacie PDF ]