/// <summary> /// Writes a register value to HW using the specified IRegDriver. /// The software copy of the registers value is updated. /// </summary> /// <param name="driver"></param> /// <param name="registerValue">the value to write to HW></param> public void Write(IRegDriver driver, T registerValue) { if (IsReadOnly) { if (mLogger.IsLoggingEnabledFor(LogLevel.Warning)) { mLogger.LogAppend(new LoggingEvent(LogLevel.Warning, string.Format( "Attempt to write to RO register ({0} / 0x{1:x}", Name, Offset), this)); } return; } // mValue and the corresponding write to hardware must be thread safe lock ( mResource ) { mValue = registerValue; if (mRegSet != null) { mRegSet.DriverWrite(driver); } else { DriverWrite(driver); } NeedApply = false; } }
/// <summary> /// Perform a write of the register using the register's software copy of its /// value without performing any of the normal checks (such as "is this register /// writable?"). This method is intended for advanced operations such as /// used by RegSet -- please consider using Write( IRegDriver, T ) instead. /// /// For AddrDataReg32 this is a "device register" write operation. This is composed of /// 1) Optionally, a write mWriteValue to mRwField (if non-null) /// 2) A write to mAddrField (value == Offset) /// 3) A write to mAddrField /// If all the fields are part of the same register, all the fields are written at the same time. /// </summary> /// <param name="driver">IRegDriver used for memory mapped register operation (forwarded to BitField.Apply)</param> public override void DriverWrite(IRegDriver driver) { // REVISIT: should put lock around these otherwise in a multi threaded environment // you can't be sure the value logged was actually the value written!!! // ACTUALLY, we could just get a thread safe, stack copy of mValue at start of this // method and use it internally. This would fix 1 problem. It wouldn't however fix // the problem of really not being sure the write took place when it was supposed to! if (mLogger.IsLoggingEnabledFor(LogLevel.Fine)) { mLogger.LogAppend(new RegisterLoggingEvent(LogLevel.Fine, mValue, this) { Operation = RegisterLoggingEvent.OperationType.RegWrDR }); } // Make sure control and address fields are set... if (mRwField != null) { mRwField.Value = mWriteValue; } mAddrField.Value = Offset; mDataField.Value = mValue; // *** THIS IMPLEMENTATION ASSUMES ALL IBitField OBJECTS BELONG TO THE SAME REGISTER *** // NOTE: DriverWrite() always writes to the HW ... so set Force=true mDataField.Apply(driver, true); }
/// <summary> /// Call Apply() of the associated register. This conditionally writes the register's /// value (if dirty) to hardware using the specified driver. /// </summary> /// <param name="driver"></param> /// <param name="forceApply"></param> public virtual void Apply(IRegDriver driver, bool forceApply) { if (mWriteDelegate != null) { mWriteDelegate(driver, mBitFieldValue); } }
/// <summary> /// Creates the device register set (typed registers). /// Note that the BAR and offset can be specified by the caller so the same RegisterSet /// class can be used to define multiple unique RegisterSet instances (different offset /// and or BAR). /// </summary> /// <param name="manager">the IRegManager instance to add this RegisterSet to</param> /// <param name="instrument">the IInstrument instance these registers are for</param> /// <param name="groupName">the group name used to access this RegisterSet from IRegManager</param> /// <param name="registerSetOffset">an offset added to all register offsets</param> /// <param name="barIndex">the BAR to use</param> public ReceiverRegisterSet(IRegManager manager, IInstrument module, string groupName, int registerSetOffset, int barIndex) { // Create the factory RegFactory regFactory = new RegFactory(registerSetOffset, module, Reg32.ConstructReg); // Determine which IRegDriver (determines default BAR) IRegDriver regDriver = (barIndex >= module.RegDrivers.Length) ? null : module.RegDrivers[barIndex]; if (regDriver == null) { throw new InternalApplicationException("ReceiverRegisterSet requires RegDriver for BAR" + barIndex); } // Create the register definitions Registers = regFactory.CreateRegArray( mRegisterDefinitions, typeof(ReceiverRegister), regDriver, module.Name); regFactory.CreateBitFields(mBitFieldDefinitions, Registers, module.Name, string.Empty); if (manager != null) { // Adding as a group creates an IDirtyBit and attaches to each register manager.AddGroup(groupName, this); } SoftwareFpgaReset = new Reg32T <SoftwareFpgaResetBF>((Reg32)Registers[(Int32)ReceiverRegister.SoftwareFpgaReset]); RfStatus = new Reg32T <RfStatusBF>((Reg32)Registers[(Int32)ReceiverRegister.RfStatus]); FpgaVersion = new Reg32T <FpgaVersionBF>((Reg32)Registers[(Int32)ReceiverRegister.FpgaVersion]); Reserved = new Reg32T <ReservedBF>((Reg32)Registers[(Int32)ReceiverRegister.Reserved]); RfControl1 = new Reg32T <RfControl1BF>((Reg32)Registers[(Int32)ReceiverRegister.RfControl1]); RfControl2 = new Reg32T <RfControl2BF>((Reg32)Registers[(Int32)ReceiverRegister.RfControl2]); RfControl3 = new Reg32T <RfControl3BF>((Reg32)Registers[(Int32)ReceiverRegister.RfControl3]); }
/// <summary> /// Construct a register with the specified register attributes /// </summary> /// <param name="name">register name</param> /// <param name="offset">offset (BAR offset for memory mapped register)</param> /// <param name="bfType">enumerated type of BitFields contained by this register.</param> /// <param name="regType">register type/attribute (one or more bits from RegType, e.g. Cmd|RO).</param> /// <param name="driver">The default driver the register uses to read/write.</param> protected Reg(string name, Int32 offset, Type bfType, IRegDriver driver, RegType regType) : base(name, offset, bfType, regType, driver) { if (bfType != null) { // mFields = new TRegField[Enum.GetNames(BFenumType).Length]; // PREPARING FOR UNUSED COMMON BITS Array values = Enum.GetValues(bfType); mFirstBFvalue = (byte)((int)values.GetValue(0)); mNumBFs = (byte)values.Length; //int maxValue = 0; //foreach (int value in values) //{ // if (value > maxValue) // maxValue = value; // if (value < mFirstField) // mFirstField = (byte)value; //} // we create an array for enum values 0-LastBFvalue mFields = new IBitField[LastBF + 1]; // mNumBFs = (byte) (maxValue+1); } else { mFields = null; } Reset(); // reset IEnumerable index. }
/// <summary> /// Perform a write of the register using the register's software copy of its /// value without performing any of the normal checks (such as "is this register /// writable?"). This method is intended for advanced operations such as /// used by RegSet -- please consider using Write( IRegDriver, T ) instead. /// </summary> /// <returns></returns> public override void DriverWrite(IRegDriver driver) { // REVISIT: should put lock around these otherwise in a multi threaded environment // you can't be sure the value logged was actually the value written!!! // ACTUALLY, we could just get a thread safe, stack copy of mValue at start of this // method and use it internally. This would fix 1 problem. It wouldn't however fix // the problem of really not being sure the write took place when it was supposed to! //if( mLogFunctionLogElement != null ) //{ // mLogFunctionLogElement( this, // mValue, // ReferenceEquals( driver, mDriver ) ? ItemLogged.RegWr : ItemLogged.RegWrCS ); //} if (mLogger.IsLoggingEnabledFor(LogLevel.Fine)) { mLogger.LogAppend(new RegisterLoggingEvent(LogLevel.Fine, mValue, this) { Operation = (driver == null || driver.IsRecordingSession == false) ? RegisterLoggingEvent.OperationType.RegWr : RegisterLoggingEvent.OperationType.RegWrCS }); } if (driver == null) { mDriver.RegWrite(mOffset, mValue); } else { // Explicitly specify AddressSpace -- the register may be associated // with a different space than the specified driver... driver.RegWrite(mDriver.AddressSpace, mOffset, mValue); } }
public virtual void Write(IRegDriver driver, Int32[] data, int length, int offset) { if (length > mBufSizeInWords) { throw new ApplicationException(REQUESTED_SIZE_TOO_LARGE); } if (mLogger.IsLoggingEnabledFor(LogLevel.Fine)) { mLogger.LogAppend(new RegisterLoggingEvent(LogLevel.Fine, data.Length, this) { Operation = (driver == null || driver.IsRecordingSession == false) ? RegisterLoggingEvent.OperationType.BufWr32s : RegisterLoggingEvent.OperationType.BufWr32sCS }); if (mLogger.IsLoggingEnabledFor(LogLevel.Finest)) { LogBuffer32("Write Buffer32[]=", data, offset, length); } } if (driver != null) { driver.ArrayWrite(mAddr, data, length, offset); } else { mDriver.ArrayWrite(mAddr, data, length, offset); } }
/// <summary> /// Creates the device register set (typed registers). /// Note that the BAR and offset can be specified by the caller so the same RegisterSet /// class can be used to define multiple unique RegisterSet instances (different offset /// and or BAR). /// </summary> /// <param name="manager">the IRegManager instance to add this RegisterSet to</param> /// <param name="instrument">the IInstrument instance these registers are for</param> /// <param name="groupName">the group name used to access this RegisterSet from IRegManager</param> /// <param name="registerSetOffset">an offset added to all register offsets</param> /// <param name="barIndex">the BAR to use</param> public SoftwareLatchesRegisterSet(IRegManager manager, IInstrument module, string groupName, int registerSetOffset, int barIndex) { // Create the factory RegFactory regFactory = new RegFactory(registerSetOffset, module, SimulatedReg.ConstructReg); // Determine which IRegDriver (determines default BAR) IRegDriver regDriver = (barIndex >= module.RegDrivers.Length) ? null : module.RegDrivers[barIndex]; if (regDriver == null) { throw new InternalApplicationException("SoftwareLatchesRegisterSet requires RegDriver for BAR" + barIndex); } // Create the register definitions Registers = regFactory.CreateRegArray( mRegisterDefinitions, typeof(SoftwareLatchesRegister), regDriver, module.Name); regFactory.CreateBitFields(mBitFieldDefinitions, Registers, module.Name, string.Empty); if (manager != null) { // Adding as a group creates an IDirtyBit and attaches to each register manager.AddGroup(groupName, this); } LatchOne = new Reg64T <LatchOneBF>((SimulatedReg)Registers[(Int32)SoftwareLatchesRegister.LatchOne]); TxSwLatch1 = new Reg64T <TxSwLatch1BF>((SimulatedReg)Registers[(Int32)SoftwareLatchesRegister.TxSwLatch1]); RxSwLatch1 = new Reg64T <RxSwLatch1BF>((SimulatedReg)Registers[(Int32)SoftwareLatchesRegister.RxSwLatch1]); }
/// <summary> /// Write a byte array to the buffer on a specified driver. /// </summary> /// <param name="driver"></param> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="length"></param> public virtual void Write(IRegDriver driver, byte[] data, int startIndex, int length) { if (length > mBufSizeInBytes) { throw new ApplicationException(REQUESTED_SIZE_TOO_LARGE); } if (mLogger.IsLoggingEnabledFor(LogLevel.Fine)) { mLogger.LogAppend(new RegisterLoggingEvent(LogLevel.Fine, length, this) { Operation = RegisterLoggingEvent.OperationType.BufWr8s }); if (mLogger.IsLoggingEnabledFor(LogLevel.Finest)) { LogBuffer8("Write Buffer8[]=", data, startIndex, length); } } if (driver == null) { mDriver.ArrayWrite(mAddr, data, startIndex, length); } else { driver.ArrayWrite(mAddr, data, startIndex, length); } }
public override void Apply(IRegDriver driver, bool forceApply) { if (IsApplyEnabled && (NeedApply || (forceApply && IsForceAllowed))) { // This check (for RO and NoValue) filters out a very small percentage of write requests // but takes almost as long as the 'if statement' immediately preceding. The preceding // check typically filters out >90% of the Apply calls ... so it makes more sense (performance // wise) to have the RO | NoValue check here rather than as the first statement of Apply() if (IsReadOnly || IsNoValue) { // Don't generate a warning here -- calling Apply on any register is legal/OK return; } if (mRegSet != null) { mRegSet.DriverWrite(driver); } else { DriverWrite(driver); } NeedApply = false; } }
public void DriverWrite(IRegDriver driver) { for (int i = mIndexFirstReg; i <= mIndexLastReg; i++) { mRegArray[i].DriverWrite(driver); } mRegSetDirty = false; // handled in individual DriverWrite cmds? }
public SimulatedReg(string name, Int32 offset, Type bfType, IRegDriver driver, RegType eRegType) : base(name, offset, bfType, driver, eRegType) { }
public void WriteRegister(IRegDriver activeDriver, int offset, int value) { if (offset >= Size) { throw new Exception("Index out of range."); } mRegArray[mIndexFirstReg + offset].Value = value; mRegArray[mIndexFirstReg + offset].Apply(activeDriver, true); }
/// <summary> /// Writes the value to HW. /// /// Most implementations preserve all bits outside the current bitfield definition, /// but some implementations (CommandField32, CommandField64) clear all other bits. /// </summary> /// <param name="driver">driver(port in moonstone terms) to write to.</param> /// <param name="value">value to write.</param> public virtual void Write(IRegDriver driver, int value) { // NOTE: use WriteBitField to get the appropriate register logging WriteBitField(value); if (mWriteDelegate != null) { mWriteDelegate(driver, mBitFieldValue); } }
/// <summary> /// Creates a 32 bit buffer region /// </summary> /// <param name="barOffset">starting byte address in BAR0 space.</param> /// <param name="sizeInBytes">buffer size in bytes.</param> /// <param name="driver">driver buffer uses to access the buffer.</param> /// <param name="name">buffer name.</param> public Buffer32(string name, Int32 barOffset, Int32 sizeInBytes, IRegDriver driver) { mName = name; mDriver = driver; mAddr = barOffset; mBufSizeInWords = sizeInBytes / 4; mBufSizeInBytes = sizeInBytes; IsApplyEnabled = true; }
public Reg32(string name, Int32 offset, Type bfType, IRegDriver driver, RegType eRegType) : base(name, offset, bfType, driver, eRegType) { // Typically (not always), Reg32 is memory mapped IsMemoryMapped = true; }
/// <summary> /// Construct a "device register" -- the read and write operations are delegated to BitFields /// (which could be part of memory mapped registers or other more complicated objects). /// Although an IRegDriver is specified, it isn't directly used by AddrDataReg32 but it is /// "forwarded" to the BitFields (addrField, dataField, rwField) which may be required for /// "control stream operations". /// /// If rwField is non-null, it will be set to 1 for writes and 0 for reads /// /// *** THIS IMPLEMENTATION ASSUMES ALL IBitField OBJECTS BELONG TO THE SAME REGISTER *** /// </summary> /// <param name="name">register name</param> /// <param name="offset">offset (internal "device address" of the register ... written to 'addrField')</param> /// <param name="bfType">enumerated type of BitFields contained by this register.</param> /// <param name="driver">the default driver, not directly used by AddrDataReg32 but may be used by the addrField, dataField, rwField</param> /// <param name="addrField">BitField for the device's internal register address (offset will be written to this)</param> /// <param name="dataField">BitField for the device's internal register data</param> /// <param name="rwField">Optional BitField for indicating a read or write operation</param> public AddrDataReg32(string name, Int32 offset, Type bfType, IRegDriver driver, IBitField addrField, IBitField dataField, IBitField rwField) : this(name, offset, bfType, driver, RegType.RW, addrField, dataField, rwField, 0, 1) { }
/// <summary> /// Writes the value to HW. If Cmd or Event register, all other bit fields are set to 0. /// /// NOTE: for Cmd and Event registers this IS NOT the same as Value=value;Apply(); /// </summary> /// <param name="driver">driver(port in moonstone terms) to write to.</param> /// <param name="value">value to write.</param> public override void Write(IRegDriver driver, int value) { if (mRegister.IsCommand || mRegister.IsEvent) { mRegister.Write64(driver, (value << mStartBit) & mMask); // forces all other bits zero. } else { mRegister.Write64(driver, UpdateRegField(value)); } }
public new static IRegister ConstructReg(string name, RegDef regDef, IRegDriver driver, int baseAddr, object[] args) { var newRegister = new SimulatedReg(name, regDef.BARoffset + baseAddr, regDef.BFenum, driver, regDef.RegType); return(newRegister); }
public static IRegister ConstructReg(string name, RegDef regDef, IRegDriver driver, int baseAddr, object[] args) { return(new Reg32(name, regDef.BARoffset + baseAddr, regDef.BFenum, driver, regDef.RegType)); }
public override void DriverWrite(IRegDriver driver) { if (mLogger.IsLoggingEnabledFor(LogLevel.Fine)) { mLogger.LogAppend(new RegisterLoggingEvent(LogLevel.Fine, mValue, this) { Operation = (driver == null || driver.IsRecordingSession == false) ? RegisterLoggingEvent.OperationType.RegWr : RegisterLoggingEvent.OperationType.RegWrCS }); } // ignore the driver ... this is always simulated mSimulatedHardware = mValue; }
/// <summary> /// Delegate method used to construct a register. This method will be passed to a /// register factory such as RegFactory to create registers from definitions. /// </summary> /// <param name="name">register name</param> /// <param name="regDef">reference to RegDef struct.</param> /// <param name="driver">driver to read this type of Treg register.</param> /// <param name="baseAddr">typically 0, but this additional base address can be /// used to add to the register address specified in the RegDef struct. /// Currently only used for CannotReadDirectly registers, so is typically 0.</param> /// <param name="args">arbitrary array of objects for use by the delegate ... normally /// used to specify register-type specific arguments</param> /// <returns>a reference to the register Treg created.</returns> public static IRegister ConstructNonMemoryMappedControlReg(string name, RegDef regDef, IRegDriver driver, int baseAddr, object[] args) { return(new Reg32(name, regDef.BARoffset + baseAddr, regDef.BFenum, driver, regDef.RegType) { IsMemoryMapped = false }); }
/// <summary> /// Construct a register with the specified register attributes /// </summary> /// <param name="name">register name</param> /// <param name="bfType">enumerated type of BitFields contained by this register.</param> /// <param name="regType">register type/attribute (one or more bits from RegType, e.g. Cmd|RO).</param> /// <param name="driver">The default driver the register uses to read/write.</param> /// <param name="registers">The list of registers to duplicate values over</param> public DuplicateReg32(string name, Type bfType, IRegDriver driver, RegType regType, IRegister[] registers) : base(name, 0, bfType, driver, regType) // 0 offset { mRegisters = registers; // ReSharper disable DoNotCallOverridableMethodsInConstructor if (Fields.Length == 0) { throw new InternalApplicationException("A DuplicateReg32 definition must have at least one field."); } // ReSharper restore DoNotCallOverridableMethodsInConstructor }
/// <summary> /// Construct a "device register" -- the read and write operations are delegated to BitFields /// (which could be part of memory mapped registers or other more complicated objects). /// Although an IRegDriver is specified, it isn't directly used by AddrDataReg32 but it is /// "forwarded" to the BitFields (addrField, dataField, rwField) which may be required for /// "control stream operations". /// /// If rwField is non-null, it will be set to writeValue for writes and readValue for reads /// /// *** THIS IMPLEMENTATION ASSUMES ALL IBitField OBJECTS BELONG TO THE SAME REGISTER *** /// </summary> /// <param name="name">register name</param> /// <param name="offset">offset (internal "device address" of the register ... written to 'addrField')</param> /// <param name="bfType">enumerated type of BitFields contained by this register.</param> /// <param name="driver">the default driver, not directly used by AddrDataReg32 but may be used by the addrField, dataField, rwField</param> /// <param name="regType">register type/attribute (one or more bits from RegType, e.g. Cmd|RO).</param> /// <param name="addrField">BitField for the device's internal register address (offset will be written to this)</param> /// <param name="dataField">BitField for the device's internal register data</param> /// <param name="rwField">Optional BitField for indicating a read or write operation</param> /// <param name="readValue">The value written to rwField for read operations</param> /// <param name="writeValue">The value written to rwField for write operations</param> public AddrDataReg32(string name, Int32 offset, Type bfType, IRegDriver driver, RegType regType, IBitField addrField, IBitField dataField, IBitField rwField, int readValue, int writeValue) : base(name, offset, bfType, driver, regType) { mAddrField = addrField; mDataField = dataField; mRwField = rwField; mReadValue = readValue; mWriteValue = writeValue; }
/// <summary> /// Creates the device register set (typed registers). /// Note that the BAR and offset can be specified by the caller so the same RegisterSet /// class can be used to define multiple unique RegisterSet instances (different offset /// and or BAR). /// </summary> /// <param name="manager">the IRegManager instance to add this RegisterSet to</param> /// <param name="instrument">the IInstrument instance these registers are for</param> /// <param name="groupName">the group name used to access this RegisterSet from IRegManager</param> /// <param name="registerSetOffset">an offset added to all register offsets</param> /// <param name="barIndex">the BAR to use</param> public SourceRegisterSet(IRegManager manager, IInstrument module, string groupName, int registerSetOffset, int barIndex) { // Create the factory RegFactory regFactory = new RegFactory(registerSetOffset, module, Reg32.ConstructReg); // Determine which IRegDriver (determines default BAR) IRegDriver regDriver = (barIndex >= module.RegDrivers.Length) ? null : module.RegDrivers[barIndex]; if (regDriver == null) { throw new InternalApplicationException("SourceRegisterSet requires RegDriver for BAR" + barIndex); } // Create the register definitions Registers = regFactory.CreateRegArray( mRegisterDefinitions, typeof(SourceRegister), regDriver, module.Name); regFactory.CreateBitFields(mBitFieldDefinitions, Registers, module.Name, string.Empty); if (manager != null) { // Adding as a group creates an IDirtyBit and attaches to each register manager.AddGroup(groupName, this); } RFCntrl_path = new Reg32T <RFCntrl_pathBF>((Reg32)Registers[(Int32)SourceRegister.RFCntrl_path]); RFCntrl_Port = new Reg32T <RFCntrl_PortBF>((Reg32)Registers[(Int32)SourceRegister.RFCntrl_Port]); LOCntrl = new Reg32T <LOCntrlBF>((Reg32)Registers[(Int32)SourceRegister.LOCntrl]); IQCntrl = new Reg32T <IQCntrlBF>((Reg32)Registers[(Int32)SourceRegister.IQCntrl]); PowerCntrl = new Reg32T <PowerCntrlBF>((Reg32)Registers[(Int32)SourceRegister.PowerCntrl]); RFAtten = new Reg32T <RFAttenBF>((Reg32)Registers[(Int32)SourceRegister.RFAtten]); TempSensorCntrl = new Reg32T <TempSensorCntrlBF>((Reg32)Registers[(Int32)SourceRegister.TempSensorCntrl]); AbusRegister = new Reg32T <AbusRegisterBF>((Reg32)Registers[(Int32)SourceRegister.AbusRegister]); RFUtility = new Reg32T <RFUtilityBF>((Reg32)Registers[(Int32)SourceRegister.RFUtility]); RfStatus = new Reg32T <RfStatusBF>((Reg32)Registers[(Int32)SourceRegister.RfStatus]); ChipID_L = new Reg32T <ChipID_LBF>((Reg32)Registers[(Int32)SourceRegister.ChipID_L]); ChipID_H = new Reg32T <ChipID_HBF>((Reg32)Registers[(Int32)SourceRegister.ChipID_H]); RfFpgaVersion = new Reg32T <RfFpgaVersionBF>((Reg32)Registers[(Int32)SourceRegister.RfFpgaVersion]); RfFpgaSoftReset = new Reg32T <RfFpgaSoftResetBF>((Reg32)Registers[(Int32)SourceRegister.RfFpgaSoftReset]); }
/// <summary> /// Delegate method used to construct a register. This method will be passed to a /// register factory such as RegFactory to create registers from definitions. /// </summary> /// <param name="name">register name</param> /// <param name="regDef">reference to RegDeg struct.</param> /// <param name="driver">driver to read this type of Treg register.</param> /// <param name="baseAddr">typically 0, but this additional base address can be /// used to add to the register address specified in the RegDef struct. /// Currently only used for CannotReadDirectly registers, so is typically 0.</param> /// <param name="args">arbitrary array of objects for use by the delegate ... For /// AddrDataReg32 this must contain (in order): /// Address Field (RegField32) /// Data Field (RegField32) /// Control Field (RegField32) /// </param> /// <returns>a reference to the register Treg created.</returns> public static IRegister ConstructReg(string name, RegDef regDef, IRegDriver driver, int baseAddr, object[] args) { if (args == null || args.Length < 3) { throw new InvalidParameterException( "Expected 'args' to contain 3 RegField32 values [address, data, control]."); } switch (args.Length) { case 3: return(new AddrDataReg32(name, regDef.BARoffset + baseAddr, regDef.BFenum, driver, regDef.RegType, (IBitField)args[0], (IBitField)args[1], (IBitField)args[2])); case 5: return(new AddrDataReg32(name, regDef.BARoffset + baseAddr, regDef.BFenum, driver, regDef.RegType, (IBitField)args[0], (IBitField)args[1], (IBitField)args[2], (int)args[3], (int)args[4])); default: throw new InvalidParameterException( "Expected 'args' to contain 3 or 5 values: 3 RegField32 values [address, data, control] and, optionally, read control value and write control value."); } }
/// <summary> /// Perform a write of the register using the register's software copy of its /// value without performing any of the normal checks (such as "is this register /// writable?"). This method is intended for advanced operations such as /// used by RegSet -- please consider using Write( IRegDriver, T ) instead. /// </summary> /// <returns></returns> public override void DriverWrite(IRegDriver driver) { // REVISIT: should put lock around these otherwise in a multi threaded environment // you can't be sure the value logged was actually the value written!!! // ACTUALLY, we could just get a thread safe, stack copy of mValue at start of this // method and use it internally. This would fix 1 problem. It wouldn't however fix // the problem of really not being sure the write took place when it was supposed to! if (mLogger.IsLoggingEnabledFor(LogLevel.Fine)) { mLogger.LogAppend(new RegisterLoggingEvent(LogLevel.Fine, mValue, this) { Operation = RegisterLoggingEvent.OperationType.RegWrDR }); } // Lazily initialize the common mask... if (mCommonMask == 0) { // We need to create the common mask from the defined fields... foreach (var field in Fields) { mCommonMask |= (uint)field.Mask; } } uint invMask = ~mCommonMask; // All the registers should get written with exactly the same value... foreach (var register in mRegisters) { // Need to remove the existing bits, then // 'OR' in the register value in case the registers use other bit fields // for something else. register.Value32 = (int)((uint)(register.Value32 & invMask) | (uint)mValue); // NOTE: DriverWrite() always writes to the HW ... so set Force=true register.Apply(driver, true); } }
/// <summary> /// Construct a register with the specified register attributes /// </summary> /// <param name="name">register name</param> /// <param name="offset">offset (BAR offset for memory mapped register)</param> /// <param name="bfType">enumerated type of BitFields contained by this register.</param> /// <param name="regType">register type/attribute (one or more bits from RegType, e.g. Cmd|RO).</param> /// <param name="driver">The default driver the register uses to read/write.</param> protected RegBase(string name, Int32 offset, Type bfType, RegType regType, IRegDriver driver) { mName = name; mOffset = offset; mBFType = bfType; mDriver = driver; mRegType = regType; // Simplify various checks... (the masking operations are taking way longer than expected) IsReadOnly = (mRegType & RegType.RO) != 0; IsWriteOnly = (mRegType & RegType.WO) != 0; IsVolatileReadWrite = (mRegType & RegType.VolatileRw) != 0; IsNoForce = (mRegType & RegType.NoForce) != 0; IsForceAllowed = (mRegType & RegType.NoForce) == 0; IsNoValue = (mRegType & RegType.NoValue) != 0; IsNoValueFilter = (mRegType & RegType.NoValueFilter) != 0; IsCannotReadDirectly = (mRegType & RegType.CannotReadDirectly) != 0; IsCommand = (mRegType & RegType.Cmd) != 0; IsEvent = (mRegType & RegType.Event) != 0; // Mark as dirty unless type is NoForce mDirty = IsForceAllowed; IsApplyEnabled = true; // Be default, registers are NOT memory mapped (typically the memory // mapped implementations are Reg32 and Reg64) IsMemoryMapped = false; // Optionally initialize the cached value from hardware if ((mRegType & RegType.InitializeAtCreation) != 0) { // ReSharper disable DoNotCallOverridableMethodsInConstructor // I know this is a virtual method -- must be careful in the implementation to only access RegBase objects UpdateRegVal(); // ReSharper restore DoNotCallOverridableMethodsInConstructor } }
public abstract void Apply(IRegDriver driver, bool forceApply);
/// <summary> /// Writes the value to HW. /// </summary> /// <param name="driver">driver(port in moonstone terms) to write to.</param> /// <param name="value">value to write.</param> public abstract void Write(IRegDriver driver, int value);