diff --git a/hurricane/src/analog/CMakeLists.txt b/hurricane/src/analog/CMakeLists.txt index 6434b401..b2680251 100644 --- a/hurricane/src/analog/CMakeLists.txt +++ b/hurricane/src/analog/CMakeLists.txt @@ -21,6 +21,7 @@ MatrixParameter.cpp MCheckBoxParameter.cpp StepParameter.cpp + StringParameter.cpp BJT.cpp BJTFamily.cpp BJTFamilyNames.cpp @@ -71,6 +72,7 @@ PySimpleCurrentMirror.cpp PySpinBoxParameter.cpp PyStepParameter.cpp + PyStringParameter.cpp PyFloatParameter.cpp PyTransistor.cpp PyTransistorFamily.cpp @@ -108,6 +110,7 @@ hurricane/analog/SimpleCurrentMirror.h hurricane/analog/SpinBoxParameter.h hurricane/analog/StepParameter.h + hurricane/analog/StringParameter.h hurricane/analog/FloatParameter.h hurricane/analog/TransistorFamily.h hurricane/analog/TransistorFamilyNames.h @@ -141,6 +144,7 @@ hurricane/analog/PySimpleCurrentMirror.h hurricane/analog/PySpinBoxParameter.h hurricane/analog/PyStepParameter.h + hurricane/analog/PyStringParameter.h hurricane/analog/PyFloatParameter.h hurricane/analog/PyTransistorFamily.h hurricane/analog/PyTransistor.h diff --git a/hurricane/src/analog/PyAnalog.cpp b/hurricane/src/analog/PyAnalog.cpp index 4781012c..4528831e 100644 --- a/hurricane/src/analog/PyAnalog.cpp +++ b/hurricane/src/analog/PyAnalog.cpp @@ -40,6 +40,7 @@ #include "hurricane/analog/PyFormFactorParameter.h" #include "hurricane/analog/PyMCheckBoxParameter.h" #include "hurricane/analog/PySpinBoxParameter.h" +#include "hurricane/analog/PyStringParameter.h" #include "hurricane/analog/PyStepParameter.h" #include "hurricane/analog/PyFloatParameter.h" #include "hurricane/analog/PyCapacitiesParameter.h" @@ -97,6 +98,7 @@ extern "C" { PyMCheckBoxParameter_LinkPyType(); PySpinBoxParameter_LinkPyType(); PyStepParameter_LinkPyType(); + PyStringParameter_LinkPyType(); PyFloatParameter_LinkPyType(); PyCapacitiesParameter_LinkPyType(); PyMatrixParameter_LinkPyType(); @@ -129,6 +131,7 @@ extern "C" { PYTYPE_READY_SUB( FormFactorParameter , Parameter ) PYTYPE_READY_SUB( MCheckBoxParameter , Parameter ) PYTYPE_READY_SUB( SpinBoxParameter , Parameter ) + PYTYPE_READY_SUB( StringParameter , Parameter ) PYTYPE_READY_SUB( StepParameter , Parameter ) PYTYPE_READY_SUB( FloatParameter , Parameter ) PYTYPE_READY_SUB( CapacitiesParameter , Parameter ) @@ -160,6 +163,7 @@ extern "C" { __cs.addType( "ffpar" , &PyTypeFormFactorParameter , "" , false, "parameter" ); __cs.addType( "mcboxpar" , &PyTypeMCheckBoxParameter , "" , false, "parameter" ); __cs.addType( "sboxpar" , &PyTypeSpinBoxParameter , "" , false, "parameter" ); + __cs.addType( "strpar" , &PyTypeStringParameter , "" , false, "parameter" ); __cs.addType( "steppar" , &PyTypeStepParameter , "" , false, "parameter" ); __cs.addType( "floatpar" , &PyTypeFloatParameter , "" , false, "parameter" ); __cs.addType( "capspar" , &PyTypeCapacitiesParameter , "" , false, "parameter" ); @@ -221,6 +225,8 @@ extern "C" { PyModule_AddObject( module, "MCheckBoxParameter" , (PyObject*)&PyTypeMCheckBoxParameter ); Py_INCREF( &PyTypeSpinBoxParameter ); PyModule_AddObject( module, "SpinBoxParameter" , (PyObject*)&PyTypeSpinBoxParameter ); + Py_INCREF( &PyTypeStringParameter ); + PyModule_AddObject( module, "StringParameter" , (PyObject*)&PyTypeStringParameter ); Py_INCREF( &PyTypeStepParameter ); PyModule_AddObject( module, "StepParameter" , (PyObject*)&PyTypeStepParameter ); Py_INCREF( &PyTypeFloatParameter ); diff --git a/hurricane/src/analog/PyParameter.cpp b/hurricane/src/analog/PyParameter.cpp index a2ec1103..4530107f 100644 --- a/hurricane/src/analog/PyParameter.cpp +++ b/hurricane/src/analog/PyParameter.cpp @@ -21,6 +21,7 @@ #include "hurricane/analog/PyFormFactorParameter.h" #include "hurricane/analog/PyMCheckBoxParameter.h" #include "hurricane/analog/PySpinBoxParameter.h" +#include "hurricane/analog/PyStringParameter.h" #include "hurricane/analog/PyStepParameter.h" #include "hurricane/analog/PyFloatParameter.h" @@ -121,6 +122,9 @@ extern "C" { StepParameter* stepParameter = dynamic_cast(object); if (stepParameter) return PyStepParameter_Link(stepParameter); + StringParameter* stringParameter = dynamic_cast(object); + if (stringParameter) return PyStringParameter_Link(stringParameter); + FloatParameter* floatParameter = dynamic_cast(object); if (floatParameter) return PyFloatParameter_Link(floatParameter); diff --git a/hurricane/src/analog/PyStringParameter.cpp b/hurricane/src/analog/PyStringParameter.cpp new file mode 100644 index 00000000..0d8b9ca4 --- /dev/null +++ b/hurricane/src/analog/PyStringParameter.cpp @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2020-2020, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | H u r r i c a n e A n a l o g | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyStringParameter.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/analog/PyStringParameter.h" + + +namespace Isobar { + +using namespace Hurricane; +using namespace Analog; + +extern "C" { + + +#undef ACCESS_OBJECT +#undef ACCESS_CLASS +#define ACCESS_OBJECT _baseObject._object +#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject) +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(StringParameter,stringParameter,function) + +#if defined(__PYTHON_MODULE__) + +// +=================================================================+ +// | "PyStringParameter" Python Module Code Part | +// +=================================================================+ + + + DirectGetStringAttribute( PyStringParameter_getValue, getValue , PyStringParameter, StringParameter) + DirectSetCStringAttribute(PyStringParameter_setValue, setValue , PyStringParameter, StringParameter) + + + // --------------------------------------------------------------- + // PyStringParameter Attribute Method table. + + PyMethodDef PyStringParameter_Methods[] = + { { "getValue" , (PyCFunction)PyStringParameter_getValue , METH_NOARGS + , "Self explanatory." } + , { "setValue" , (PyCFunction)PyStringParameter_setValue , METH_VARARGS + , "Self explanatory." } + , { NULL, NULL, 0, NULL } /* sentinel */ + }; + + + // +-------------------------------------------------------------+ + // | "PyStringParameter" Object Methods | + // +-------------------------------------------------------------+ + + + PythonOnlyDeleteMethod(StringParameter) + PyTypeObjectLinkPyType(StringParameter) + + +#else // End of Python Module Code Part. + +// +=================================================================+ +// | "PyStringParameter" Shared Library Code Part | +// +=================================================================+ + + + LinkCreateMethod(StringParameter) + PyTypeInheritedObjectDefinitions(StringParameter, Parameter) + + +#endif // End of Shared Library Code Part. + +} // extern "C". + +} // Isobar namespace. diff --git a/hurricane/src/analog/StepParameter.cpp b/hurricane/src/analog/StepParameter.cpp index 2c414d87..8b590245 100644 --- a/hurricane/src/analog/StepParameter.cpp +++ b/hurricane/src/analog/StepParameter.cpp @@ -10,7 +10,7 @@ // | Authors : Christophe Alexandre | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | -// | C++ Module : "./StepParameter.cpp" | +// | C++ Module : "./StepParameter.cpp" | // +-----------------------------------------------------------------+ diff --git a/hurricane/src/analog/StringParameter.cpp b/hurricane/src/analog/StringParameter.cpp new file mode 100644 index 00000000..154f3a1c --- /dev/null +++ b/hurricane/src/analog/StringParameter.cpp @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2020-2020, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | H u r r i c a n e A n a l o g | +// | | +// | Authors : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./StringParameter.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/analog/StringParameter.h" + + +namespace Analog { + + using std::string; + + + string StringParameter::_getTypeName () const + { return "StringParameter"; } + + + std::string StringParameter::_getString () const + { + string s = Super::_getString(); + s.insert( s.size()-1, " \""+_value+"\"" ); + return s; + } + + + Record* StringParameter::_getRecord () const + { + Record* record = Super::_getRecord(); + record->add( getSlot( "_value", &_value ) ); + return record; + } + + + + +} // Analog namespace. diff --git a/hurricane/src/analog/Transistor.cpp b/hurricane/src/analog/Transistor.cpp index bb6cb26b..67cb57d4 100644 --- a/hurricane/src/analog/Transistor.cpp +++ b/hurricane/src/analog/Transistor.cpp @@ -46,10 +46,15 @@ namespace Analog { tr->_postCreate(deviceName); tr->createConnections(bulkConnected); - tr->addStepParameter("B.w" , 1, 1, 1); - tr->addStepParameter("D.w" , 1, 1, 1); - tr->addStepParameter("G.w" , 1, 1, 1); - tr->addStepParameter("S.w" , 1, 1, 1); + tr->addStepParameter( "B.w" , 1, 1, 1 ); + tr->addStepParameter( "D.w" , 1, 1, 1 ); + tr->addStepParameter( "G.w" , 1, 1, 1 ); + tr->addStepParameter( "S.w" , 1, 1, 1 ); + + tr->addStringParameter( "B.t" , "bX" ); + tr->addStringParameter( "D.t" , "b0" ); + tr->addStringParameter( "G.t" , "t0" ); + tr->addStringParameter( "S.t" , "b1" ); UpdateSession::close(); return tr; } diff --git a/hurricane/src/analog/hurricane/analog/Device.h b/hurricane/src/analog/hurricane/analog/Device.h index 4349b3db..6998dcce 100644 --- a/hurricane/src/analog/hurricane/analog/Device.h +++ b/hurricane/src/analog/hurricane/analog/Device.h @@ -14,14 +14,13 @@ // +-----------------------------------------------------------------+ -#ifndef ANALOG_DEVICE_H -#define ANALOG_DEVICE_H - +#pragma once #include "hurricane/Cell.h" #include "hurricane/analog/StepParameter.h" #include "hurricane/analog/FloatParameter.h" #include "hurricane/analog/CapacitorParameter.h" #include "hurricane/analog/ChoiceParameter.h" +#include "hurricane/analog/StringParameter.h" #include "hurricane/analog/SpinBoxParameter.h" #include "hurricane/analog/MCheckBoxParameter.h" #include "hurricane/analog/FormFactorParameter.h" @@ -71,6 +70,7 @@ namespace Analog { inline Hurricane::Library* getSubDevicesLibrary (); inline void addParameter ( Parameter* parameter ); inline StepParameter* addStepParameter ( const std::string name, long min, long max, long step ); + inline StringParameter* addStringParameter ( const std::string name, const std::string value="" ); inline FloatParameter* addFloatParameter ( const std::string name, float value=0.0 ); inline CapacitorParameter* addCapacitorParameter ( const std::string name, long value ); inline SpinBoxParameter* addSpinBoxParameter ( const std::string name, long min, long max ); @@ -110,6 +110,13 @@ namespace Analog { return stepParameter; } + inline StringParameter* Device::addStringParameter ( const std::string name, const std::string value ) + { + StringParameter* stringParameter = new StringParameter( name, value ); + addParameter( stringParameter ); + return stringParameter; + } + inline FloatParameter* Device::addFloatParameter ( const std::string name, float value ) { FloatParameter* floatParameter = new FloatParameter( name, value ); @@ -171,5 +178,3 @@ namespace Analog { INSPECTOR_P_SUPPORT(Analog::Device); - -#endif // ANALOG_DEVICE_H diff --git a/hurricane/src/analog/hurricane/analog/PyStepParameter.h b/hurricane/src/analog/hurricane/analog/PyStepParameter.h index 3859c956..ee07e706 100644 --- a/hurricane/src/analog/hurricane/analog/PyStepParameter.h +++ b/hurricane/src/analog/hurricane/analog/PyStepParameter.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef ANALOG_PY_STEP_PARAMETER_H -#define ANALOG_PY_STEP_PARAMETER_H - +#pragma once #include "hurricane/analog/PyParameter.h" #include "hurricane/analog/StepParameter.h" @@ -51,5 +49,3 @@ extern "C" { } // extern "C". } // Isobar namespace. - -#endif // ANALOG_PY_STEP_PARAMETER_H diff --git a/hurricane/src/analog/hurricane/analog/PyStringParameter.h b/hurricane/src/analog/hurricane/analog/PyStringParameter.h new file mode 100644 index 00000000..1b908291 --- /dev/null +++ b/hurricane/src/analog/hurricane/analog/PyStringParameter.h @@ -0,0 +1,51 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2020-2020, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | H u r r i c a n e A n a l o g | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/analog/PyStringParameter.h" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include "hurricane/analog/PyParameter.h" +#include "hurricane/analog/StringParameter.h" + + +namespace Isobar { + +extern "C" { + +// ------------------------------------------------------------------- +// Python Object : "PyStringParameter". + + typedef struct { + PyParameter _baseObject; + } PyStringParameter; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyHurricane.cpp". + + extern PyTypeObject PyTypeStringParameter; + extern PyMethodDef PyStringParameter_Methods[]; + + extern PyObject* PyStringParameter_Link ( Analog::StringParameter* object ); + extern void PyStringParameter_LinkPyType (); + + +#define IsPyStringParameter(v) ( (v)->ob_type == &PyTypeStringParameter ) +#define PYSTRINGPARAMETER(v) ( (PyStringParameter*)(v) ) +#define PYSTRINGPARAMETER_O(v) ( PYSTRINGPARAMETER(v)->_baseObject->_baseObject._object ) + + +} // extern "C". + +} // Isobar namespace. diff --git a/hurricane/src/analog/hurricane/analog/StepParameter.h b/hurricane/src/analog/hurricane/analog/StepParameter.h index 5fc5e583..8bf3ea46 100644 --- a/hurricane/src/analog/hurricane/analog/StepParameter.h +++ b/hurricane/src/analog/hurricane/analog/StepParameter.h @@ -10,12 +10,10 @@ // | Authors : Christophe Alexandre | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | -// | C++ Header : "./hurricane/analog/Choices.h" | +// | C++ Header : "./hurricane/analog/StepParameter.h" | // +-----------------------------------------------------------------+ -#ifndef ANALOG_STEP_PARAMETER_H -#define ANALOG_STEP_PARAMETER_H - +#pragma once #include "hurricane/analog/Parameter.h" @@ -56,5 +54,3 @@ namespace Analog { INSPECTOR_PR_SUPPORT(Analog::StepParameter); - -#endif // ANALOG_STEP_PARAMETER_H diff --git a/hurricane/src/analog/hurricane/analog/StringParameter.h b/hurricane/src/analog/hurricane/analog/StringParameter.h new file mode 100644 index 00000000..9e0d8513 --- /dev/null +++ b/hurricane/src/analog/hurricane/analog/StringParameter.h @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2009-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | H u r r i c a n e A n a l o g | +// | | +// | Authors : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/analog/StringParameter.h" | +// +-----------------------------------------------------------------+ + +#pragma once +#include "hurricane/analog/Parameter.h" + + +namespace Analog { + + class StringParameter : public Parameter { + public: + typedef Parameter Super; + public: + inline StringParameter ( std::string id, std::string v ); + inline std::string getValue () const; + inline operator std::string () const; + inline void setValue ( std::string ); + virtual std::string _getTypeName () const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + private: + std::string _value; + }; + + + inline StringParameter::StringParameter ( std::string id, std::string v ): Parameter(id), _value(v) {} + inline std::string StringParameter::getValue () const { return _value; } + inline StringParameter::operator std::string () const { return getValue(); } + inline void StringParameter::setValue ( std::string value ) { _value = value; } + + +} // Analog namespace. + + +INSPECTOR_PR_SUPPORT(Analog::StringParameter); diff --git a/hurricane/src/analog/hurricane/analog/Transistor.h b/hurricane/src/analog/hurricane/analog/Transistor.h index 2fffa6b7..2d41e16e 100644 --- a/hurricane/src/analog/hurricane/analog/Transistor.h +++ b/hurricane/src/analog/hurricane/analog/Transistor.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef ANALOG_TRANSISTOR_H -#define ANALOG_TRANSISTOR_H - +#pragma once #include "hurricane/analog/TransistorFamily.h" namespace Analog { @@ -46,5 +44,3 @@ namespace Analog { } // Analog namespace. - -#endif // ANALOG_TRANSISTOR_H diff --git a/hurricane/src/analog/hurricane/analog/TransistorFamily.h b/hurricane/src/analog/hurricane/analog/TransistorFamily.h index 56b96128..f37ca19a 100644 --- a/hurricane/src/analog/hurricane/analog/TransistorFamily.h +++ b/hurricane/src/analog/hurricane/analog/TransistorFamily.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef ANALOG_TRANSISTOR_FAMILY_H -#define ANALOG_TRANSISTOR_FAMILY_H - +#pragma once #include "hurricane/DbU.h" #include "hurricane/analog/Device.h" #include "hurricane/analog/MetaTransistor.h" @@ -175,5 +173,3 @@ namespace Analog { } // Analog namespace. - -#endif // ANALOG_TRANSISTOR_FAMILY_H diff --git a/karakaze/python/analogdesign.py b/karakaze/python/analogdesign.py index c2b038c7..aeba3eaa 100644 --- a/karakaze/python/analogdesign.py +++ b/karakaze/python/analogdesign.py @@ -424,6 +424,11 @@ class AnalogDesign ( object ): if (len(dspec) > 12): device.getParameter( 'NERC' ).setValue(int (dspec[12])) if (len(dspec) > 13): device.getParameter( 'NIRC' ).setValue(int (dspec[13])) + if (len(dspec) > 14): + for wiringSpec in dspec[14].split(' '): + fields = wiringSpec.split('.') + if len(fields) > 1: + device.getParameter( fields[0]+'.t' ).setValue( fields[1] ) if not (dspec[7] is None): device.setMint ( dspec[7] ) if dspec[8]: device.setExternalDummy( dspec[8] ) diff --git a/oroshi/python/capacitorrouted.py b/oroshi/python/capacitorrouted.py index ea305fdf..413e5e3d 100644 --- a/oroshi/python/capacitorrouted.py +++ b/oroshi/python/capacitorrouted.py @@ -159,8 +159,15 @@ class RoutMatchedCapacitor( CapacitorUnit, CapacitorStack, VerticalRoutingTracks xMax = self.abutmentBox.getXMax() else: trackSpacing = (self.vRoutingTrack_width + self.vpitch + self.metal3Width)/2 - xMin = self.vRoutingTrackXCenter[ 0][firstVRTId] - trackSpacing - xMax = self.vRoutingTrackXCenter[-1][ lastVRTId] + trackSpacing + if firstVRTId > len(self.vRoutingTrackXCenter[ 0]): + xMin = self.abutmentBox.getXMin() - trackSpacing + else: + xMin = self.vRoutingTrackXCenter[ 0][firstVRTId] - trackSpacing + + if lastVRTId > len(self.vRoutingTrackXCenter[-1]): + xMax = self.abutmentBox.getXMax() + trackSpacing + else: + xMax = self.vRoutingTrackXCenter[-1][ lastVRTId] + trackSpacing width = xMax - xMin widthAdjust = width % (2*self.vpitch) diff --git a/oroshi/python/wip_transistor.py b/oroshi/python/wip_transistor.py index 47fcb355..a5dd63eb 100644 --- a/oroshi/python/wip_transistor.py +++ b/oroshi/python/wip_transistor.py @@ -60,18 +60,29 @@ def layout ( device, bbMode ): gw = str(device.getParameter( 'G.w' ).getValue()) sw = str(device.getParameter( 'S.w' ).getValue()) - diffMap = { 'D':'D', 'S':'S', 'Dw':dw, 'Sw':sw, 'Gw':gw, 'Bw':bw } + bt = device.getParameter( 'B.t' ).getValue() + dt = device.getParameter( 'D.t' ).getValue() + gt = device.getParameter( 'G.t' ).getValue() + st = device.getParameter( 'S.t' ).getValue() + + diffMap = { 'D':'D', 'S':'S' + , 'Dw':dw, 'Sw':sw, 'Gw':gw, 'Bw':bw + , 'Dt':dt, 'St':st, 'Gt':gt, 'Bt':bt + } if device.isSourceFirst(): trace( 100, '\tUse sourceFirst.\n' ) - diffMap = { 'D':'S', 'S':'D', 'Dw':sw, 'Sw':dw, 'Gw':gw, 'Bw':bw } + diffMap = { 'D':'S', 'S':'D' + , 'Dw':sw, 'Sw':dw, 'Gw':gw, 'Bw':bw + , 'Dt':dt, 'St':st, 'Gt':gt, 'Bt':bt + } - wirings = '{D}.b0.{Dw} G.t0.{Gw} {S}.b1.{Sw}' + wirings = '{D}.{Dt}.{Dw} G.{Gt}.{Gw} {S}.{St}.{Sw}' for i in range(device.getM() - 1): - if i%2: wirings += ' G.t0.{Gw} {S}.b1.{Sw}' - else: wirings += ' G.t0.{Gw} {D}.b0.{Dw}' + if i%2: wirings += ' G.{Gt}.{Gw} {S}.{St}.{Sw}' + else: wirings += ' G.{Gt}.{Gw} {D}.{Dt}.{Dw}' for i in range(device.getExternalDummy()): - wirings = 'B.bX.{Bw} B.bX.{Bw} ' + wirings - wirings += ' B.bX.{Bw} B.bX.{Bw}' + wirings = 'B.{Bt}.{Bw} B.{Bt}.{Bw} ' + wirings + wirings += ' B.{Bt}.{Bw} B.{Bt}.{Bw}' stack.setWirings( wirings.format( **diffMap ) ) stack.doLayout ( bbMode )