- Notifications
You must be signed in to change notification settings - Fork11
Automatic generation of real number models from analog circuits
License
sgherbst/msdsl
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
msdsl is a tool for generating synthesizable real number models (RNMs) for analog circuits for use in FPGA emulation. It is part of the mixed-signal emulation framework that includesvreal andanasymod.
> pip install msdsl
If you get a permissions error when running thepip command, you can try adding the--user flag. This will causepip to install packages in your user directory rather than to a system-wide location.
If you are a developer ofmsdsl, it is more convenient to clone and install the GitHub repository:
> git clone https://github.com/sgherbst/msdsl.git>cd msdsl> pip install -e.
msdsl allows you to describe analog blocks at a variety of abstraction levels. As a simple example, suppose that you want to model an RC filter with a fixed-timestep equation. That can be expressed with the followingmsdsl code:
frommsdslimport*frommathimportexpr,c,dt=1e3,1e-9,0.1e-6m=MixedSignalModel('rc')x=m.add_analog_input('x')y=m.add_analog_output('y')a=exp(-dt/(r*c))m.set_next_cycle(y,a*y+ (1-a)*x)m.compile_and_print(VerilogGenerator())
The first thing to notice is thatmsdsl is imported just like any other Python package. This allows you to instantiate aMixedSignalModel
object that is used to described analog behaviors and generate Verilog code. Next, an analog input (x) and analog output (y) are declared. Theset_next_cycle
command implements the discrete-time equation:
y[k+1] = a*y[k] + (1-a)*x[k]
Users can specify the clock and reset signals that control the initialization and updating of this equation; they default to macrosCLK_MSDSL
andRST_MSDSL
when unspecified.
On the last line, the Verilog code is generated and printed out, resulting in something like this:
`include"svreal.sv"modulerc #( `DECL_REAL(x), `DECL_REAL(y)) ( `INPUT_REAL(x), `OUTPUT_REAL(y));// Assign signal: y `MUL_CONST_REAL(0.9048374180359596, y, tmp0); `MUL_CONST_REAL(0.09516258196404037,x, tmp1); `ADD_REAL(tmp0, tmp1, tmp2); `DFF_INTO_REAL(tmp2, y, `RST_MSDSL, `CLK_MSDSL,1'b1,0);endmodule
This code makes use of macros fromsvreal, which is a library that provides a flexible, synthesizable real-number type.
Finally, note that althoughcompile_and_print
is used in this example, you may find it more useful to usecompile_to_file
in practice, sincemsdsl is often used to generate model files for use in building an emulator.
msdsl provides a number of convenient features for building models, such as operator overloading, synthesizable functions, and noise.
msdsl signals can be declared as analog or digital, and internal or external. Digital signals default to 1-bit, unsigned, but their width and signedness can be specified. Analog signals are real values with a specified +/- range that is used to compute fixed-point formats. It is generally only necessary to specify ranges for model I/O and state variables, sincemsdsl can automatically figure out the rest.
Here are some examples of signal declarations inmsdsl:
frommsdslimport*m=MixedSignalModel('model')a=m.add_analog_input('a')b=m.add_digital_output('b',signed=True,width=8)c=m.add_analog_state('c',init=1.23,range_=4.56)d=m.add_digital_signal('d',width=4)
Note the optionalinit
argument used for state variables. Although not shown here, it is also available for digital signals.
The two basic types of assignments inmsdsl areset_this_cycle andset_next_cycle.set_this_cycle acts like anassign
statement in Verilog, whichset_next_cycle acts like a synchronous assignment in analways
block. Here are some examples:
frommsdslimport*m=MixedSignalModel('model')a=m.add_analog_input('a')b=m.add_analog_output('b')c=m.add_analog_state('c',init=1.23,range_=4.56)m.set_next_cycle(c,0.9*c+0.1*a)d=m.set_this_cycle('d',6.78*c+7.89*a)# create a new signal, 'd'm.set_this_cycle(b,0.88*d)# assign to existing signal
Many Python operators for arithmetic, comparison, and bitwise operations are overloaded inmsdsl, allowing you to write down expressions conveniently. Currently supported operators include+
,-
,*
,~
,&
,|
,^
,<<
,>>
,<
,>
,<=
,>=
,==
, and!=
. The true division operator,/
, is only partially supported: dividing by constants works, but dividing by variables does not.
msdsl makes it possible to convert Python functions into synthesizable approximations. Here's an example where that feature is used to implement a variable-timestep RC filter:
importnumpyasnpfrommsdslimport*r,c=1e3,1e-9m=MixedSignalModel('rc')x=m.add_analog_input('x')dt=m.add_analog_input('dt')y=m.add_analog_output('y')func=lambdadt:np.exp(-dt/(r*c))f=m.make_function(func,domain=[0,10*r*c],numel=512,order=1)a=m.set_from_sync_func('a',f,dt)x_prev=m.cycle_delay(x,1)y_prev=m.cycle_delay(y,1)m.set_this_cycle(y,a*y_prev+ (1-a)*x_prev)m.compile_and_print(VerilogGenerator())
func
is a regular Python function, and it is converted into anmsdslFunction
via themake_function
command. This generates a piecewise-polynomial approximation of the function over a specified domain. In this example, a piecewise-linear approximation is used (order=1
) with 512 segments (numel=512
) and the domain is 10 RC time constants (domain=[0, 10*r*c]
). By default, inputs outside of the domain will return the value at the closer edge of the domain.
set_from_sync_func
generates hardware to implement the function, meaning thatmake_funcion
can be called once, and then applied multiple times withset_from_sync_func
. This is convenient since it generates more concise output code.
msdsl
also supports single-input, multi-output functions. This is important because it reduces the hardware overhead as compared to completely independent invocations of the same function. Here's an example:
importnumpyasnpfrommsdslimport*m=MixedSignalModel('model')x=m.add_analog_input('x')y1=m.add_analog_output('y1')y2=m.add_analog_output('y2')func1=lambdat:np.sin(t)func2=lambdat:np.cos(t)f=m.make_function([func1,func2],domain=[-np.pi,np.pi],numel=512,order=1)m.set_from_sync_func([y1,y2],f,x)m.compile_and_print(VerilogGenerator())
The main difference as compared to the previous example is thatmake_function
andset_from_sync_func
are called with a list of functions/output variables.
msdsl provides a means for generating different kinds of pseudorandom noise: uniform, Gaussian, and arbitrary distributions:
frommsdslimport*m=MixedSignalModel('model')# uniform noisem.set_this_cycle('a',m.uniform_signal(min_val=-1.23,max_val=4.56))# Gaussian noisem.set_gaussian_noise('b',std=1.23,mean=4.56,gen_type=...)# arbitrary noise distribution# specify via the inverse cumulative distribution functioninv_cdf=lambdax: ...inv_cdf_func=m.make_function(inv_cdf,domain=[0.0,1.0])m.set_this_cycle('c',m.arbitrary_noise(inv_cdf_func))
All noise generators depend on a pseudorandom integer generator, which can be specified with the optionalgen_type
parameter ('lcg'
,'mt19937'
,'lfsr'
). The highest-quality generator is MT19937, but it is more resource-intensive, and takes many emulator cycles to start up. The linear congruential generator (LCG) is an exact implementation of the random number generator called for in the Verilog-2001 specification. The default is a simple linear feedback shift register ('lfsr'
). Random seed values are automatically generated for random number generators, but can be explictly specified as well.
Up until this point, we have considered the low-level features provided bymsdsl to implement modeling strategies, butmsdsl also has a bunch of common model abstractions that are ready to use.
msdsl provides a method for writing down symbolic systems of linear differential equations, which are solved at compile time (i.e., through matrix exponentiation) to produce a simple FPGA implementation.
frommsdslimport*r,c=1e3,1e-9m=MixedSignalModel('rc',dt=0.1e-6)x=m.add_analog_input('x')y=m.add_analog_output('y')m.add_eqn_sys([c*Deriv(y)== (x-y)/r])m.compile_and_print(VerilogGenerator())
msdsl supports an extension to systems of linear differential equations, in which expressions can take one of several forms, depending on digital inputs. These expressions are built with theeqn_case
command. In the example below, a resistor is shorted out by a switch when the digital signals
is one. The number of cases can be greater than 2, if the digital select signal has multiple bits.
frommsdslimport*r,rsw,c=1e3,100,1e-9m=MixedSignalModel('rc',dt=0.1e-6)x=m.add_analog_input('x')s=m.add_digital_input('s')y=m.add_analog_output('y')g=eqn_case([1/r,1/r+1/rsw], [s])m.add_eqn_sys([c*Deriv(y)== (x-y)*g])m.compile_and_print(VerilogGenerator())
msdsl supports a type of "netlist", where analog components like resistors, capacitors, and inductors are instantiated. Internally, this generates symbolic KCL and KVL equations, which are solved at compile time using the previously-described differential equation interface. Switches and diodes are supported in a limited way, in which they are either "ON" or "OFF", changing their Thevenin equivalent representation. For diodes, additional logic is generated to determine whether the diode is on or off during each timestep.
The example below is a netlist-style description of an RC filter whose resistor can be shorted out with a switch.
frommsdslimport*r,rsw,c=1e3,100,1e-9m=MixedSignalModel('rc',dt=0.1e-6)x=m.add_analog_input('x')s=m.add_digital_input('s')y=m.add_analog_output('y')circ=m.make_circuit()gnd=circ.make_ground()circ.capacitor('net_y',gnd,c,voltage_range=RangeOf(y))circ.resistor('net_x','net_y',r)circ.switch('net_x','net_y',s,rsw)circ.voltage('net_x',gnd,x)circ.add_eqns(AnalogSignal('net_y')==y)m.compile_and_print(VerilogGenerator())
msdsl also allows users to specify analog dynamics with transfer functions. The user provides the coefficients of numerator and denominator polynomials, using the same style ascont2discrete.
frommsdslimport*r,c=1e3,1e-9m=MixedSignalModel('rc',dt=0.1e-6)x=m.add_analog_input('x')y=m.add_analog_output('y')m.set_tf(x,y, [[1], [r*c,1]])m.compile_and_print(VerilogGenerator())
We are currently adding higher-level abstractions that represent the function of entire blocks. This includes a saturation nonlinearity (SaturationModel
), a lossy-channel, specified from S-parameters (S4PModel
), and a continuous-time linear equalization model (CTLEModel
), which is specified by pole/zero values. These models are implemented using a new variable-timestep discretization developed at Stanford.
frommsdsl.templates.saturationimportSaturationModelm1=SaturationModel(-1,'dB',module_name='m1')frommsdsl.templates.channelimportS4PModelm2=S4PModel(s4p_file='myfile.s4p',dtmax=100e-12,module_name='m2')frommsdsl.templates.ldsimportCTLEModelm3=CTLEModel(fz=1e9,fp1=2e9,fp2=10e9,dtmax=100e-12,fmodule_name='m3')
About
Automatic generation of real number models from analog circuits