Engee 文档
Notebook

扰频器

本示例以加扰器模型为例,讨论了在Engee中使用C函数验证生成代码的可能性。

加扰器是对数字流进行可逆变换以赋予其随机序列的属性而不改变传输速率的设备或算法。 此示例使用带有伪随机二进制序列(PRBS)的加扰,该序列由长度为15的LFSR生成,初始值为100101010000000。

接下来,我们来看看实现的加扰和解扰方案。 它和该算法操作的按位比较如下图所示。

image_3.png

让我们使用我们描述的启动函数运行此模型,并保存位错误的结果。

In [ ]:
function run_model(name_model)
    Path = string(@__DIR__) * "/" * name_model * ".engee"
    
    if name_model in [m.name for m in engee.get_all_models()] # Проверка условия загрузки модели в ядро
        model = engee.open( name_model ) # Открыть модель
        model_output = engee.run( model, verbose=true ); # Запустить модель
    else
        model = engee.load( Path, force=true ) # Загрузить модель
        model_output = engee.run( model, verbose=true ); # Запустить модель
        engee.close( name_model, force=true ); # Закрыть модель
    end
    return model_output
end
Out[0]:
run_model (generic function with 1 method)
In [ ]:
@time run_model("Scrambler_descrambler")
BER = simout["Scrambler_descrambler/Error Rate Calculation.Output_1"];
BER = collect(BER)
BER[end-3:end,:]
Building...
Progress 0%
Progress 18%
Progress 100%
Progress 100%
 10.704403 seconds (527.95 k allocations: 38.180 MiB, 5.61% compilation time)
Out[0]:
4×2 DataFrame
Rowtimevalue
Float64Array…
19.97[0.0, 0.0, 998.0]
29.98[0.0, 0.0, 999.0]
39.99[0.0, 0.0, 1000.0]
410.0[0.0, 0.0, 1001.0]

正如我们所看到的,算法工作正常。 现在让我们继续代码生成器的设置。 下面的屏幕截图显示了以下几点。 目标平台被选择为Verilog,并禁用生成代码中的注释(这样做是为了在视觉上简化其可读性),并启用C函数生成以验证生成的代码。
image.png

现在让我们开始生成代码和验证模型。

In [ ]:
engee.generate_code(
"$(@__DIR__)/Scrambler_descrambler.engee",
"$(@__DIR__)/V_Code",
subsystem_name="Scrambler_descrambler"
)
[ Info: Generated code and artifacts: /user/start/examples/codegen/scrambler_Verilog/V_Code

我们来分析一下生成的文件。
image.png
正如我们所看到的,除了verilog代码文件之外,该文件夹还包含:

  1. 可执行文件.so
  2. 库文件。h
  3. 码文件。jl

让我们从最后一个开始。 该文件允许我们生成一个包含C函数的模型,以便与原始模型进行比较。
``'茱莉亚

这是Scrambler_descrambler_Scrambler_descrambler生成代码的验证脚本。

运行此代码以创建一个验证模型,其中包含一个CFunction块,其行为与原始模型类似。

CFunction变量

start_code="""
Scrambler_descrambler_Scrambler_descrambler_init();"""
output_code="""
Scrambler_descrambler_Scrambler_descrambler_eval(In1,
&Out1;);
"""
terminate_code="""
Scrambler_descrambler_Scrambler_descrambler_final();"""

接近/接近

试试engee。close("Scrambler_descrambler_Scrambler_descrambler_verification";force=true)捕获结束

创建

恩吉。创建("Scrambler_descrambler_Scrambler_descrambler_verification")

添加块

恩吉。add_block("/Basic/Ports&Subsystems/In1","Scrambler_descrambler_Scrambler_descrambler_verification/In1")
恩吉。add_block("/Basic/User-Defined Functions/C Function","Scrambler_descrambler_Scrambler_descrambler_verification/")
恩吉。add_block("/Basic/Ports&Subsystems/Out1","Scrambler_descrambler_Scrambler_descrambler_verification/Out1")

编辑块参数

恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/In1","PortDimensions"=>"()")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/In1","SignalType"=>"real")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/In1","OutDataTypeStr"=>"Bool")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","OutputCode"=>output_code,"StartCode"=>start_code,"TerminateCode"=>terminate_code)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","输入"=>1)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","输出"=>1)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","InputPort1Label"=>"In1")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","InputPort1VarName"=>"In1")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","InputPort1Type"=>"bool")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","InputPort1Size"=>"()")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","SampleTime"=>"0.01")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","参数"=>0)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","OutputPort1Label"=>"Out1")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","OutputPort1VarName"=>"Out1")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","OutputPort1Type"=>"bool")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","OutputPort1Size"=>"()")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","IncludeDirectories"=>"/user/my_projects/Demo/Work/scrambler_Verilog/V_Code/obj_dir")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","LibraryDirectories"=>"/user/my_projects/Demo/Work/scrambler_Verilog/V_Code/obj_dir")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","Headers"=>"Scrambler_descrambler_Scrambler_descrambler_cfn_api。h")
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C函数","库"=>"libScrambler_descrambler_Scrambler_descrambler.so ")

编辑模型参数

恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification","FixedStep"=>0.01)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification","StartTime"=>0.0)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification","StopTime"=>10)
恩吉。set_param!("Scrambler_descrambler_Scrambler_descrambler_verification","EnableMultiTasking"=>false)

添加行

恩吉。add_line("Scrambler_descrambler_Scrambler_descrambler_verification","In1/1","C函数/1")
恩吉。add_line("Scrambler_descrambler_Scrambler_descrambler_verification","C函数/1","Out1/1")

储蓄

恩吉。save("Scrambler_descrambler_Scrambler_descrambler_verification.engee";力=真)


让我们运行这个文件并获得C功能块,我们稍后将与原始模型进行比较。

<img src="/helpcenter/stable/_next/static/media/example_resources/scrambler_Verilog_media/image_2.png" alt="image_2.png" class="notebook-media">

基于生成的文件执行的结果。jl我们得到了一个访问库和可执行文件的块。 现在让我们基于这个块构建几个模型。 让我们从一个类似于原始模型的模型开始。

<img src="/helpcenter/stable/_next/static/media/example_resources/scrambler_Verilog_media/image_3.png" alt="image_3.png" class="notebook-media">


让我们运行这个模型并比较执行时间和模型的一般行为。

In [ ]:
@time run_model("Scrambler_descrambler_verification")
BER = simout["Scrambler_descrambler_verification/Error Rate Calculation.Output_1"];
BER = collect(BER)
BER[end-3:end,:]
Building...
Progress 0%
Progress 18%
Progress 99%
Progress 100%
  5.424469 seconds (205.50 k allocations: 15.873 MiB)
Out[0]:
4×2 DataFrame
Rowtimevalue
Float64Array…
19.97[0.0, 0.0, 998.0]
29.98[0.0, 0.0, 999.0]
39.99[0.0, 0.0, 1000.0]
410.0[0.0, 0.0, 1001.0]

正如我们所看到的,模型比原始模型更快,并且通过BER判断,与原始模型相同。 现在让我们比较一般模型中的这些块。
image.png

让我们运行这个模型并比较错误。

In [ ]:
run_model("Scrambler_add_verification")
err = simout["Scrambler_add_verification/err"];
println("Кол-во ошибок: $(sum(collect(err).value))")
Building...
Progress 0%
Progress 22%
Progress 100%
Progress 100%
Кол-во ошибок: 0

从结果中我们可以看到,这些块是相同的,这意味着代码生成是正确执行的。

结论

在这个例子中,我们演示了一个代码生成验证工具,并且还成功生成了scrambler模型的verilog代码。

image.png 代码本身如下所示。 ``'verilog 模块Scrambler_descrambler_Scrambler_descrambler( 输入时钟, 重置, io_In1, 输出io_Out1 );

注册单元_13_state;
reg UnitDelay_2_state;
reg UnitDelay_13_1_state;
reg UnitDelay_2_1_state;
注册单元_14_state;
reg UnitDelay_14_1_state;
reg UnitDelay_3_state;
reg UnitDelay_3_1_state;
注册单元_4_state;
reg UnitDelay_4_1_state;
reg UnitDelay_state;
reg UnitDelay_1_state;
注册单元_5_state;
注册单元_5_1_state;
reg UnitDelay_6_state;
reg UnitDelay_1_1_state;
reg UnitDelay_1_2_state;
reg UnitDelay_6_1_state;
注册单元_7_state;
reg UnitDelay_7_1_state;
注册单元_8_state;
reg UnitDelay_8_1_state;
注册单元_9_state;
reg UnitDelay_9_1_state;
注册单元_10_state;
reg UnitDelay_10_1_state;
注册单元_11_state;
reg UnitDelay_11_1_state;
注册单元_12_state;
reg UnitDelay_12_1_state;
线LogicalOperator=UnitDelay_13_state^UnitDelay_14_state;
线LogicalOperator_1=UnitDelay_13_1_state^UnitDelay_14_1_state;
总是@(posedge时钟)开始
如果(重置)开始
UnitDelay_13_state<=1'0;
UnitDelay_2_state<=1'0;
UnitDelay_13_1_state<=1'0;
UnitDelay_2_1_state<=1'0;
UnitDelay_14_state<=1'0;
UnitDelay_14_1_state<=1'0;
UnitDelay_3_state<=1'0;
UnitDelay_3_1_state<=1'0;
UnitDelay_4_state<=1'0;
UnitDelay_4_1_state<=1'0;
UnitDelay_state<=1'0;
UnitDelay_1_state<=1'0;
UnitDelay_5_state<=1'0;
UnitDelay_5_1_state<=1'0;
UnitDelay_6_state<=1'0;
UnitDelay_1_1_state<=1'0;
UnitDelay_1_2_state<=1'0;
UnitDelay_6_1_state<=1'0;
UnitDelay_7_state<=1'0;
UnitDelay_7_1_state<=1'0;
UnitDelay_8_state<=1'0;
UnitDelay_8_1_state<=1'0;
UnitDelay_9_state<=1'0;
UnitDelay_9_1_state<=1'0;
UnitDelay_10_state<=1'0;
UnitDelay_10_1_state<=1'0;
UnitDelay_11_state<=1'0;
UnitDelay_11_1_state<=1'0;
UnitDelay_12_state<=1'0;
UnitDelay_12_1_state<=1'0;
结束
其他开始
UnitDelay_13_state<=UnitDelay_12_state;
UnitDelay_2_state<=UnitDelay_1_1_state;
UnitDelay_13_1_state<=UnitDelay_12_1_state;
UnitDelay_2_1_state<=UnitDelay_1_2_state;
UnitDelay_14_state<=UnitDelay_13_state;
UnitDelay_14_1_state<=UnitDelay_13_1_state;
UnitDelay_3_state<=UnitDelay_2_1_state;
UnitDelay_3_1_state<=UnitDelay_2_state;
UnitDelay_4_state<=UnitDelay_3_state;
UnitDelay_4_1_state<=UnitDelay_3_1_state;
UnitDelay_state<=LogicalOperator;
UnitDelay_1_state<=LogicalOperator_1;
UnitDelay_5_state<=UnitDelay_4_1_state;
UnitDelay_5_1_state<=UnitDelay_4_state;
UnitDelay_6_state<=UnitDelay_5_1_state;
UnitDelay_1_1_state<=UnitDelay_1_state;
UnitDelay_1_2_state<=UnitDelay_state;
UnitDelay_6_1_state<=UnitDelay_5_state;
UnitDelay_7_state<=UnitDelay_6_state;
UnitDelay_7_1_state<=UnitDelay_6_1_state;
UnitDelay_8_state<=UnitDelay_7_1_state;
UnitDelay_8_1_state<=UnitDelay_7_state;
UnitDelay_9_state<=UnitDelay_8_1_state;
UnitDelay_9_1_state<=UnitDelay_8_state;
UnitDelay_10_state<=UnitDelay_9_state;
UnitDelay_10_1_state<=UnitDelay_9_1_state;
UnitDelay_11_state<=UnitDelay_10_state;
UnitDelay_11_1_state<=UnitDelay_10_1_state;
UnitDelay_12_state<=UnitDelay_11_state;
UnitDelay_12_1_state<=UnitDelay_11_1_state;
结束
结束//总是@(posedge)
分配io_Out1=LogicalOperator_1LogicalOperatorio_In1;
端模,端模