/*****************************************************************************
 Custom Instruction Example - Saturation Add
 ===========================================
 Simon Moore, Feb 2010

 This package provides an example of a NIOS custom instruction which computes
 saturation add on unsigned 32-bit numbers (i.e. adding two very large
 numbers doen't overflow but instead results in the maximum integer).
 *****************************************************************************/

package CustomInstruction_SaturationAdd;

import FIFO::*;
import GetPut::*;
import ClientServer::*;
import CustomInstructionNIOS::*;
import Clocks::*;


// module which describes the the functionality of new instruction
module mkSaturationAdd(Get#(NIOS_Two_OperandsT) operands, Put#(Maybe#(NIOSwordT)) result, Empty inf);
   
   rule do_instruction;
      let ops <- operands.get(); // get operands
      UInt#(33) res = extend(unpack(pack(ops.opA))) + extend(unpack(pack(ops.opB)));
      if((res>>32) == 1) res = (1<<32)-1;
      result.put(tagged Valid unpack(pack(truncate(res))));
   endrule
endmodule



// top-level module which glues the Bluespec wrapper (from CustomIntructionNIOS)
// to the new instruction module
(* synthesize,
   clock_prefix = "nios_custom_instruction_slave_clk",
   reset_prefix = "nios_custom_instruction_slave_reset" *)
module mkCustomInstruction_SaturationAdd(NIOS_Two_Operand_Physical_Embedded_Ifc);
   // expose and the invert reset since Bluespec uses a negative reset
   // and the NIOS interface uses a negative reset
   Reset rst <- exposeCurrentReset;
   Reset rst_n <- mkResetInverter(rst);
   
   // instantiate the wrapper
   NIOS_Two_Operand_Instruction_Ifc physical <-
     mkNIOS_Two_Operand_Custom_Instruction(reset_by rst_n);
   
   // instantiate the new instruction implementation
   Empty my_instruction <-
     mkSaturationAdd(physical.client.request, physical.client.response,
	reset_by rst_n);
   
   // N.B. don't put any rules here since they will receive the
   // wrong reset signal and will be held permenatnly in reset
   
   interface nios_custom = physical.nios_custom;
endmodule


endpackage: CustomInstruction_SaturationAdd
