手机‎从哪里‎下载‎最佳‎策略,win7设备安装被策略阻止到手机上面啊?

Verilog[159] verilog中的阻塞赋值和非阻塞赋值有什么区别?verilog支持阻塞与非阻塞两种赋值方式。使用阻塞赋值时,计算和赋值会立刻执行。因此但是顺序执行块中由多个阻塞赋值,他们会按照阻塞的方式顺序执行。如下所示。 always
@(posedge clk)
begin
x = a|b;
y = a&b;
z = x|y;
end
在这个例子中,所有赋值都采用的时阻塞赋值,执行时会立刻进行计算,然后完成赋值操作。因此在第三条语句中,会将前两条语句中更新后的x和y用于第三条语句的计算并赋值。在非阻塞赋值中,所有的赋值都将在当前的仿真时刻的最后执行。首先对右侧的表达式进行计算,然后才对左侧进行赋值,因此在下面的例子中,三条语句都先进行右侧语句的计算,然后再一起对左侧进行赋值操作。结果就是,第三条语句所采用的x和y是一个旧值,并不是前两条语句在这个仿真时刻改变后的值。 always
@(posedge clk)
begin
x <= a|b;
y <= a&b;
z <= x|y;
end
[160] 下面的两个例子综合时需要多少个Flip-Flop? 1)
always @(posedge clk)
begin
B = A;
C = B;
end
2)
always @(posedge clk)
begin
B <= A;
C <= B;
end
1)一个;2)两个第一种情况下,A的值赋予B,B更新后的值在同一个周期将赋予C,因此只需要一个触发器即可第二种情况下,B更新后的值,在下一个周期才能赋予C,需要两个触发器实现[161] 下列代码的输出是什么? always @(posedge clk)
begin
a = 0;
a <=1;
$display("a=%0b", a);
end
由于非阻塞赋值只能在周期结束生效,而display语句打印的是当前值,所以结果是a=0。[162] 编写verilog代码,交换两个寄存器的值,并且不使用中间寄存器 always @(posedge clk)
begin
A<=B;
B<=A;
end
[163] 下列代码的输出是? module test;
int alpha,beta;
initial
begin
alpha = 4;
beta = 3;
beta <= beta + alpha;
alpha <= alpha + beta;
alpha = alpha - 1;
$display("Alpha=%0d Beta=%0d", alpha,beta);
end
endmodule
这些赋值在一个没有任何时钟的initial块中,所以非阻塞赋值是不起作用的,因此只关心阻塞赋值。结果是:Alpha=3 Beta=3[164] 下列两种情况下c的值会是多少(五个时间单位后)? 1)
initial begin
a=0;
b=1;
c = #5 a+b;
end
2)
initial begin
a=0;
b=1;
#5 c = a+b;
end
initial begin
a=0;
#3 a=1;
end
c=1c=2第一种情况下,c=a+b,但是需要五个时间单位的延迟以后才完成赋值第二种情况下,在c=a+b赋值完成之前,另一个initial块中,第三个时间单位时,修改了a的值,所以在计算a+b时,a=1,因此最终结果为2[165] 分析下面的代码,找出代码的错误 bit a, b, c, d, e;
always @(a, b, c) begin
e = a & b & c & d;
end
敏感列表缺失了d,这会导致仿真结果错误,而综合结果可能是正确的[166] 编写verilog模块,使用“?:”运算符实现3:1muxmodule mux31_2(inp0,inp1,inp2,sel0,sel1, outres);
input inp0, inp1, inp2, sel0, sel1;
output outres;
assign outres = sel1 ? inp2 : (sel0 ? inp1 : inp0);
endmodule
[167] 用下列两段代码进行建模,这两种代码风格有什么问题?always @(posedge clk or posedge reset)
if (reset)
X1 = 0; // reset
else
X1 = X2;
always @(posedge clk or posedge reset)
if (reset)
X2 = 1;// set
else
X2 = X1;
verilog仿真器并不能保证always块的执行顺序,在上面的代码中,由于使用了阻塞赋值,因此会导致竞争现象。如果我们使用不同的仿真器,always块的执行顺序不同可能会导致不同的结果。推荐使用非阻塞赋值。[168] 同步复位和异步复位之间有什么区别?如何使用verilog进行同步复位和异步复位建模?上电以后,使用复位进行状态设定为一个确定状态。如果对复位在时钟的边沿进行采样,那么就是同步复位。如果不依赖于时钟边沿进行复位采用,则为异步复位。下面的代码为同步复位always
@ (posedge clk) begin
if (reset) begin
ABC <=0;
end
end
下面的代码为异步复位always
@ (posedge clk or posedge reset ) begin
if (reset) begin
ABC <=0;
end
end
[169] “==”和“===”有什么区别?两者都是相等或比较运算符。“==”测检查二值逻辑相等,而“===”运算符测试四值逻辑相等。使用“==”比较四值逻辑,如果出现X或者Z,则结果为X。使用“===”比较四值逻辑,如果出现X或Z,则结果为0或1,能够正确的进行比较。[170] 如果A和B是两个3bit的变量:A = 3'b1x0 B = 3'b1x0 ,那么1)A==B 2)A===B的结果分别是?A==B只能判断非X/Z,出现X或Z,最后的结果为XA===B能够判断X/Z,结果为1[171] 用verilog建模Latch和Flip-Flop,并解释他们的不同Flip-Flop,在时钟上下沿进行采样。Latch,在使能时,一直进行采样,输出跟随输入D触发器always @ (posedge clk) begin
if(reset) begin
Q <= 0;
Qbar <= 1;
end else begin
Q <= D;
Qbar <= ~D;
end
end
锁存器always @ (D or Enable) begin
if(Enable) begin
Q <= D;
Qbar <= ~D;
end
end
[172] 编写verilog代码,检测序列10110首先设计状态机。没有检测到序列检测到1检测到10检测到101检测到1011状态机如下module seq_detector(z,x,clock,reset);
output z;
input x,clock;
input reset; //active high
reg [2:0] state,nextstate;
parameter s0=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100;
always @ (posedge clock) begin
if(reset) begin
state <=s0;
nextstate<=s0;
end else begin
state<=nextstate;
end
end
always @ (x or state)
case(state)
s0:
if(x) nextstate=s1; else nextstate=s0;
s1:
if(x) nextstate=s1; else nextstate=s2;
s2:
if(x) nextstate=s3; else nextstate=s0;
s3:
if(x) nextstate=s4; else nextstate=s2;
s4:
if(x) nextstate=s1; else nextstate=s2;
endcase
always @ (x or state)
case(state)
s4: if(x) z=1'b0; else z=1'b1;
s0,s1,s2,s3: z=1'b0;
endcase
endmodule
[173] 写一段verilog代码,根据输入的n计算斐波那契数列斐波那契数列是一种数列,每一项是通过将前两项相加而得到的。 从0和1开始,顺序为0、1、1、2、3、5、8、13、21、34,依此类推。 通常,表达式为xn = xn-1 + xn-2。 假设最大值n = 256,以下代码将生成第n个斐波那契数。 值“n”作为输入传递给模块(nth_number)module fibonacci(input clock, reset, input [7:0] nth_number, output [19:0] fibonacci_number, output number_ready);
reg [19:0] previous_value, current_value;
reg [7:0] internal_counter;
reg number_ready_r;
always @(posedge clock or posedge reset)
begin
if(reset) begin
previous_value <='d0; //1st Fibonacci Number
current_value <='d1; //2nd Fibonacci Number
internal_counter <='d1;
number_ready_r <= 0;
end else begin
if (internal_counter == (nth_number-2)) begin
number_ready_r <= 1;
end else begin
internal_counter <= internal_counter + 1;
current_value <= current_value + previous_value;
previous_value <= current_value;
number_ready_r <= 0;
end
end
end
assign fibonacci_number = current_value;
assign number_ready = number_ready_r
endmodule
[174] 写一段verilog代码,用半加器组成全加器module half_adder(input_0, input_1, sum, carry);
input input_0, input_1;
output sum, carry;
assign sum = (input_0)^(input_1);
assign carry = (input_0)&(input_1);
endmodule
module full_adder(input_0, input_1, input_2, sum, carry);
input input_0, input_1, input_2;
output sum, carry;
reg sum_intermediate, carry_intermediate_0, carry_intermediate_1;
half_adder ha1(input0,input1,sum_intermediate,carry_intermediate_0);
half_adder ha2(sum_intermediate,input2,sum,carry_intermediate_1);
assign carry = (carry_intermediate_0)|(carry_intermediate_1);
endmodule
[175] verilog中的task和function有什么区别?function不能使用任何延时语句,task可以由于1中的原因,function可以调用function,但是不能调用task。task可以调用task和funtionfuntion可以综合,task不可以function需要有通过返回参数作为输出,但是有多个输入输出参数。task不能返回任何值,但是具有多个输入或者输出参数。SystemVerilog[176] systemverilog中的reg,wire和logic有什么区别?reg和wire是Verilog中就存在的两种数据类型,而logic是SystemVerilog中引入的新数据类型。wire是一种数据类型,可以对物理导线进行建模以连接两个元素。 导线只能由连续赋值语句驱动,如果不驱动,则无法保持值。 因此,wire只能用于对组合逻辑进行建模。 reg是可以为存储数据或状态建模的数据类型。 它们需要由always块驱动,而不能由连续赋值语句驱动。 reg可用于建模顺序逻辑和组合逻辑。logic是SystemVerilog中的一种新数据类型,可用于wire和reg建模,也是四值逻辑,可以被用作reg也可以wire。[177] bit和logic有什么区别?bit是只能存储0和1的二值逻辑,而logic能够储存0、1、X和Z的四值逻辑。二值逻辑能够加速仿真速度,而如果用二值逻辑用于驱动或者采样来自RTL的信号,会导致错误采样X和Z[178] logic[7:0] 和 byte 有什么区别?byte是有符号类型,最大为127,而logic可以被声明为无符号,最大可以达到255.[179] 动态数组和关联数组,哪个更加适合模拟大型数组?例如32KB的巨大内存数组关联数组更加适合用于大型数组的建模,因为只有在讲元素写入数组时才分配内存。而动态数组需要在使用之前分配和初始化内存。例如:如果要使用动态数组对32KB的内存数组进行建模,则首先需要分配32K的空间用于读/写。但是由于关联数组内部使用哈希进行元素的搜索,所以速度也是最慢的。[180] 有一个动态数组通过下列代码进行初始化,写一段代码找出数组中所有大于3的元素int
myvalues [] = '{9,1,8,3,2,4,6},
int match_q[$];
match_q = myvalues.find with (item > 3);
[181] systemverilog中的union和struct有什么区别?struct表示不同数据类型的集合。 例如:在下面的示例中,我们定义了一个名为instruction_s的struct,该struct由24位地址和8位操作码构成。typedef struct {
bit [7:0] opcode;
bit [23:0] addr;
} instruction_s;
instruction_s current_instruction;
current_instruction.addr='h100;
可以直接引用instruction_s,也可以单独引用成员。存储struct所需的内存空间为成员之和,例如instruction_s需要32bit的空间。union是一种数据类型,可以使用有且只有一种命名成员数据类型来访问它。 与struct不同,不能访问所有成员数据类型。 分配给union的内存将是成员数据类型所需的最大内存。 如果要对诸如寄存器之类的硬件资源建模,该寄存器可以存储不同类型的值,则union很有用。 例如:如果寄存器可以存储整数和实数值,则可以按以下方式定义union:typedef
union {
int
data;
real
f_data;
}state_u;
state_u
reg_state;
reg_state.f_data = 'hFFFF_FFFF_FFFF_FFFF;
$display(" int_data =%h", reg_state.data);
在此示例中,state_u可以保存32位整数数据,也可以保存64位实数数据。 因此,为reg_state分配的内存将为64bit(两种数据类型中的较大者)。 由于所有成员数据类型都有共享内存,因此在上面的示例中,如果我们将64位值分配给reg_state.f_data,则我们也可以使用其他数据类型引用相同的32位。[182] systemverilog的function和task中“ref”和“const ref”是什么意思?ref关键字用于通过引用而不是值的方式传递参数。 子例程/函数与调用者共享句柄以访问值。 这是传递诸如类对象或对象数组之类的参数的有效方法,否则创建副本将消耗更多内存。 同样,由于调用方和function/task共享相同的引用,因此使用ref在函数内部完成的任何更改也对调用方可见。例如:这是一个CRC函数的示例,该函数需要一个大数据包作为参数来计算CRC。 通过作为参考传递,每次调用CRC函数都不需要在存储器上创建数据包的副本。function automatic int crc(ref byte packet [1000:1] );
for( int j= 1; j <= 1000; j++ ) begin
crc ^= packet[j];
end
endfunction
const关键字用于禁止函数修改传递的参数。例如:在同一个CRC函数中,可以将参数声明为“const ref”参数,如下所示,以确保原始数据包内容不会被CRC函数意外修改。function automatic int crc(const ref byte packet [1000:1] );
for( int j= 1; j <= 1000; j++ ) begin
crc ^= packet[j];
end
endfunction
[183] 下面代码中参数a和b的方向是什么?task sticky(ref int array[50], int a, b);
function和task的每一个参数都有他的方向,input,ouput,inout或者ref。如果没有显式声明,则默认与前面的参数保持一致,如果前面没有参数,则默认为输入。上述代码中,第一个参数array的方向为ref,而后续a和b没有显式声明,所以将延续前者的方向,即为ref。[184] 压缩数组和非压缩数组的区别是?压缩数组表示一组连续的bit,而非压缩数组不是。在声明上,有下面的区别bit [7:0] data ; // packed array of scalar bit types
real latency [7:0]; // unpacked array of real types
压缩数组只能由一位数据类型(bit,logic,reg)或枚举类型组成。非压缩数组能够由任意类型组成logic[31:0] addr; //packed array of logic type
class
record_c;
record_c
table[7:0];
//unpacked array of record objects
[185] packed struct和unpacked struct的区别是什么?压缩结构体是一种可以将压缩位向量作为结构成员进行访问的方法。 换句话说,如果struct的所有成员仅由位字段组成并且可以无间隙地打包在内存中,则它可以是压缩结构。 例如:在下面的struct定义中,所有成员都可以表示为位向量(int等于32位,short int到16位,byte到8位),并且一个struct可以打包到单个连续内存56bit。struct packed {
int a;
short int b;
byte c;
} pack1_s;
非压缩结构体不需要打包到连续的bit位中,因此在不同成员之间可以存在空隙。下面是一个无法压缩的结构体。struct {
string
name;
int
age;
string parent;
} record_s
[186] 下面哪个是对的?function不能消耗仿真时间task不能消耗仿真时间正确错误[187] 现有一个动态数组的大小为100,如何把他的大小定义为200,并且前100个元素例子原来的数组?动态数组使用new[]进行保留元素的内存分配。integer addr[]; // Declare the dynamic array.
addr = new[100]; // Create a 100-element array.
………
// Double the array size, preserving previous values.
addr = new[200](addr);
[188] systemverilog中case,casex和casez的区别是?case语句是选择语句,匹配表达式并执行对应的语句。下面是一个3:1MUXcase (select[1:0])
2'b00:
out_sig =
in0;
2'b01:
out_sig =
in1;
2'b10:
out_sig =
in2;
default: out_sig = 'x;
endcase
上面的例子中,如果表达式与指定的内容完全匹配,则执行后续语句,如果出现x或者z,将执行默认语句。casez是case的一个特殊版本,通常在处理较少位的译码器中使用。下面的示例中,将3位中断申请队列解码位三个独立的中断引脚,只关心对应位,而其他位无关紧要。带有优先级。casez (irq)
3'b1?? : int2 = 1'b1;
3'b?1? : int1 = 1'b1;
3'b??1 : int0 = 1'b1;
endcase
“ casex”是另一个特殊版本,除了无关项,在比较中它也忽略X和Z值。[189] 在case、casez、casex中使用的是==还是===?三者使用的都是===[190] systemverilog中的$display,$write, $monitor 和 $strobe用什么区别?$display:执行时立刻打印内容$strobe:在当前的timestep结束时打印内容$monitor:在timestep结束时,如果内容改变了,则进行打印。如果多次调用,则新的覆盖旧的。$write:和$display一样,但是不会在结尾打印换行符[191] 下面的systemverilog代码中有什么错误?task wait_packet;
Packet packet;
event packet_received;
@packet_received;
packet = new();
endtask
function void do_print();
wait_packet();
$display("packet received");
endfunction
function中不能使用任何延时语句。上面的例子中,function调用了一个耗时的task,这是非法的。[192] systemverilog中new()和new[]有什么区别?new()时systemverilog中类的构造函数。他在类中定义,并初始化对象。new[]用于动态数组的内存分配。[193] 什么是systemverilog中的前置声明?有时候,一个类有可能引用另一个尚未编译的类,这会导致编译错误。例如,如果按照下面的顺序编译Statistics和Packet,由于在编译Statistics时,Packet尚未定义,编译器将为报错。class Statistics;
Packet p1;
endclass
class Packet;
//full definition here
endclass
为了避免这个问题,类在完全定义之前,可以先进行前置声明。typedef Packet;
//forward declaration
class Statistics;
Packet p1;
endclass
class Packet;
//full definition here
endclass
[194] 下面代码有什么问题?task gen_packet(Packet pkt);
pkt = new();
pkt.dest = 0xABCD;
endtask
Packet pkt;
initial begin
gen_packet(pkt);
$display(pkt.dest);
end
这段代码在运行时,会产生空指针错误。task传入pkt句柄,而在内部为句柄创建了一个对象。在initial块中,调用了gen_packet,并修改了pkt.dest,但是对于task来说这些都是局部的。task的默认方向是input,在内部的修改句柄的指向并不能影响外部,尽管在task内部进行了对象例化并且修改了值,而实际上外部的pkt始终是空句柄。[195] systemverilog中,类成员的private、public和protect属性是什么意思?private成员只允许在class内部进行访问。这些成员在派生类中也是不可见的。public成员在class内外都可以进行访问。这些成员在派生类中是可见的。protect成员只允许在class内部进行访问。这些成员在派生类中是可见的。[196] systemverilog的类中,成员变量默认是public还是private?与C++和Java中不一样,systemverilog的类成员默认为public。[197] 什么是嵌套类?何时使用他?当一个类的定义包含另一个类的定义,则该类为嵌套类。例如,下面代码中,StringList类定义包含另一个类Node的定义。class StringList;
class Node; // Nested class for a node in a linked list.
string name;
Node link;
endclass
endclass
嵌套允许隐藏本地名称和资源的本地分配。 当需要新的类作为类实现的一部分时很有用。[198] systemverilog中的interface是什么?systemverilog中的接口用于将多个线网进行捆绑,有助于封装设计块之间的接口通信。接口可以在设计中实例化,并且可以使用单个名称进行连接,不需要显式声明所有的端口和连接。除了用于连接,接口内部还可以定义function,可以通过实例化接口调用function。接口还支持过程块和assign,这些对于协议检查和断言非常有用。下例是一个接口的简单示例:interface simple_bus; // Define the interface
logic req, gnt;
logic [7:0] addr, data;
logic [1:0] mode;
logic start, rdy;
endinterface: simple_bus
[199] 什么是modport?modport(模块端口的缩写)是接口中的一种构造,可用于分组信号并指定方向。 以下是如何使用Modport将接口进一步分组以连接到不同组件的示例。interface arb_if(input bit clk);
logic [1:0] grant, request;
logic reset;
modport TEST (output request, reset, input grant, clk);
modport DUT (input
request, reset, clk, output grant);
modport MONITOR (input request, grant, reset, clk);
endinterface
上面的示例中,相同的信号在不同的modport中具有不同的方向。[200] interface是可综合的吗?是可综合的。[201] 什么是时钟块?在interface中使用时钟块有什么好处?时钟块类似于modport,除了具备modport的信号方向指定,还能够建模信号的时序行为。下面是一个时钟块的例子。clocking sample_cb @(posedge clk);
default input #2ns output #3ns;
input a1, a2;
output b1;
endclocking
在上面的示例中,定义了一个名为sample_cb的时钟块,关联的时钟为clk。default关键字定义默认的时钟偏斜,输入为2ns,输出为3ns。输入偏斜定义了时钟采样在时钟边沿前多少个时间单位。 输出偏斜定义了时钟驱动在时钟边沿后的多少个时间单位。时钟块只能在module或者interface中定义[202] 下面两种定义时钟偏斜的方式有什么不同?1)
input
#1 step req1;
2)
input
#1ns
req1;
定义时钟偏斜有两种方式以time step为单位,这是由全局的时间精度定义的,即`timescale之间指明具体的时间长度[203] systemveirlog仿真里在一个timestep中有哪些主要的阶段?systemverilog仿真器是事件驱动的仿真器,明确定义了不同的阶段来计划和执行所有事件。在仿真中,所有的事件都以timeslot为单位进行。timeslot被划分为一组有序阶段,提供设计和测试代码之间的可预测交互。如下图所示,一个timeslot可以划分为五个主要阶段,每个阶段都可以进一步的被划分为细分的子阶段。Prepone:这是timeslot最先执行的阶段,并且只执行一次。来自测试平台对设计信号的采样发生在这个阶段。Active:Active阶段包括三个子阶段:Active,Inactive和NBA(Nonblocking assignment)阶段.RTL代码和行为代码在Active阶段执行。阻塞赋值在Active阶段执行。非阻塞赋值,RHS的计算在Active阶段执行,赋值操作在NBA阶段执行。如果由#0的赋值行为,则在inactive阶段执行。Observed:Observed用于计算property(并发断言中)表达式的触发行为。在property计算期间,通过或者失败的调度会在当前timeslot的Reactive阶段进行。Reactive:Reactive阶段包括三个子阶段:Re-Active,Re-Inactive和Re-NBA(Re-Nonblocking assignment)阶段。用于执行systemverilog中program块的阻塞赋值,#0阻塞赋值,非阻塞赋值。这个独立的响应阶段确保在测试代码执行之前,设计代码的状态已经稳定。使用OVM/UVM不需要程序块,因此Reactive阶段可能使用得不多。Postponed:Postponed阶段是当前timeslot的最后一个阶段。$monitor,$strobe和其他类似的事件在此区域执行。而$dislpay事件在Active 和 Reactive(如果在program块中调用)阶段执行[204] 根据下面的约束,哪一个选项是错误的?rand logic [15:0] a, b, c;
constraint c_abc {
a < c;
b == a;
c < 30;
b > 25;
}
b可以取26-29之间的任意值c可以取0-29之间的任意值c可以取26-29之间的任意值将约束内容取交集,c可以取27-30之间的任意值。[205] 什么是systemverilog中的unique约束?unique约束会令一组成员两两各不相同。下面是一个示例。class Test;
rand byte a[5];
rand byte b;
constraint ab_cons { unique {b, a[0:5]}; }
endclass
[206] 如何选择性的激活或者关闭一个类中的约束?//<object>.constraint_mode(0) :: 关闭对象中的所有约束
//<constraint>.constraint_mode(0) :: 选择性关闭某一个约束
class
ABC;
rand int length;
rand
byte SA;
constraint c_length { length inside [1:64];}
constraint c_sa {SA inside [1:16];}
endclass ABC abc = new();
abc.constraint_mode(0) // 关闭所有约束
abc.c_length.constraint_mode(0) // 只关闭约束c_length
[207] 现有下面的一个类,如何生成addr大于200的Packet对象?class
Packet;
rand bit[31:0] addr;
constraint c_addr { addr inside [0:100];}
endclass
大于200与内置约束冲突,所以需要先关闭内置约束,然后通过内联约束进行随机化Packet p = new();
p.c_addr.constraint_mode(0);
p.randomize with {addr > 200;};
[208] 什么是pre_randomize()和post_randomize()函数?这显示systemverilog内建的回调函数。在调用randomize之前会自动调用pre_randomize函数,之后会自动调用post_randomize函数。可以通过定义这两个函数,完成在随机化之前或者之后进行某些操作。[209] 编写一个约束,为下面对象中的动态数组生成约束,使得每个元素都小于10,数组大小也小于10class
dynamic_array;
rand unsigned int abc[];
endclass
constraint c_abc_len {
abc.size() < 10;
foreach (abc[i])
abc[i] < 10;
}
[210] 编写约束,创建随机整数数组,使数组大小在10-16之间,并且数组按照降序排列class array_abc;
rand unsigned int
myarray[];
endclass
constraint
c_abc_val {
myarray.size inside { [10:16] };
foreach (myarray[i])
if (i>0) myarray[i] < myarray[i-1];
}
[211] 如何对一个生成一个随机动态数组,并且元素两两各不相同?参考下面的代码class TestClass;
rand bit[3:0] my_array[];//dynamic array of bit[3:0]
endclass
使用unique进行约束constraint c_rand_array_uniq {
my_array.size == 6;
//or any size constraint
unique {my_array};
//unique array values
}
不适用unique进行约束,使用post_randomize回调函数完成constraint c_rand_array_inc {
my_array.size == 6 ;// or any size constraint
foreach (my_array[i])
if(i >0)
my_array[i] > my_array[i-1];
}
function post_randomize();
my_array.shuffle();
endfunction
[212] “fork - join”, “fork - join_any” 和“fork - join_none”之间有什么区别?systemverilog支持三种类型的动态进程,可以在运行时创建,并作为独立线程执行。fork-join:使用“ fork .. join”创建的进程作为单独的线程运行,但是父进程停滞不前,直到所有进程全部执行完。 如果我们看下面的示例:共有三个进程task1,task2和task3,它们将并行运行,并且只有在这三个进程全部完成之后,join语句之后的$display()才会执行。initial begin
fork
task1; // Process 1
task2; // Process 2
task3; // Process 3
join
$display(“All tasks finished”);
end
fork-join_any:使用“ fork…join_any”创建的进程作为单独的进程运行,但是父进程会在任何一个子进程完成后继续。其余进程和父进程可以并行运行。 如果我们看下面的示例:有三个进程-task1,task2和task3将并行运行。 当task1 / task2 / task3之一完成时,join_any将完成,并在其他线程可能仍在运行时执行$ display()。initial begin
fork
task1; // Process 1
task2; // Process 2
task3; // Process 3
join_any
$display(“Any one of task1/2/3 finished”);
end
fork-join_none:使用“ fork…join_none”创建的进程将作为单独的进程运行,但是父进程不会停滞并且也将并行进行。 参考以下示例,其中有三个进程-task1,task2和task3,它们将与父进程并行运行。initial begin
fork
task1; // Process 1
task2; // Process 2
task3; // Process 3
join_none
$display(“All tasks launched and running”);
end
[213] “wait fork”和“disable fork”的作用是什么?在使用“ fork..join_none”或“ fork..join_any”时,有时候需要父进程和子进程进行同步,这可以通过wait fork完成。initial begin
fork
task1; // Process 1
task2; // Process 2
join_none
$display(“All tasks launched and running”);
wait fork;
$display(“All sub-tasks finished now”);
end
类似的,disable fork可以提前将子进程停止。initial begin
fork
task1; // Process 1
task2; // Process 2
join_any
$display(“One of task1/2 completed ”);
disable
fork;
$display(“All other tasks disable now”);
end
[214] 硬约束和软约束有什么区别?systemverilog中编写的常规约束为硬约束,对成员的随机化必须始终满足约束,如果约束无解,则会导致错误。如果将约束定义为软约束,在没有外部约束的条件下,和硬约束一样,外部约束的优先级比软约束高。软约束通常用于指定随机变量的默认值和分布,并且可以被外部特定的约束覆盖。class Packet;
rand int length;
constraint length_default_c {
soft length inside {32,1024};
}
endclass
Packet p = new();
p.randomize() with { length == 1512; }
上例中,如果约束没有定义为软约束,则随机化会失败。[215] 下面每个线程的输出是什么?initial begin
for (int j=0; j<3; j++) begin
fork
automatic int result;
begin
result= j*j;
$display("Thread=%0d value=%0d", j, value);
end
join_none
wait
fork;
end
end
由于“ j”不是每个线程的动态变量,因此在生成每个线程后它会不断递增,并且当所有线程开始执行时,每个线程将看到的j都是3。因此,每个线程都将输出9。 如果每个线程打算使用不同的值,则应将“ j”的值复制到一个自动变量,如下所示:automatic int
k = j;
begin
result = k*k;
end
[216] 下面的代码会产生多少个并行的线程?fork
for (int i=0; i < 10; i++ ) begin
ABC();
end
join
for循环在fork join内,所以只有一个线程。[217] 下面的约束有什么错误?class packet;
rand bit [15:0] a, b, c;
constraint pkt_c { 0 < a < b < c; }
endclass
约束表达式中,至多只有一个关系运算符(<,<=,==,>=或>)。如果要实现变量的顺序约束,需要多个表达式。constraint
pkt_c { 0 < a;
a < b ;
b < c; }
[218] systemverilog中的虚方法和纯虚方法的区别是?在类中将方法定义为虚方法,则在派生类中可以重写这个方法。基类可以定义具有实现或不实现的虚函数,在派生类中也可以选择覆盖或不覆盖。而纯虚函数只具备函数声明,没有具体实现,在派生类中必须有具体实现。纯虚函数常用在抽象类中使用,下面是一个示例。virtual class BasePacket;
// No implementation
pure virtual function integer send(bit[31:0] data);
endclass
class EtherPacket extends BasePacket;
virtual function integer send(bit[31:0] data);
// body of the function
// that implements the send
….…
endfunction
endclass
[219] 什么是Semaphores?何时使用?Semaphores是用于控制对公用资源的机制。Semaphores可以视为在创建时具有多个钥匙的存储池,使用Semaphores访问资源时,首先要取得要是,然后才能够继续执行。通过这种机制,可以确保没有要是的进程一直等待到获取钥匙。Semaphores通常用于相互排斥,对公用资源进行访问控制以及简单同步。下面是简单的Semaphores的创建方法。semaphore smTx;
smTx = new(1);
//create the semaphore with 1 keys.
get()和try_get()分别是阻塞和非阻塞的获取钥匙的方法,put()用于返还钥匙。[220] 下面两个约束有什么不同?1)
class ABSolveBefore;
rand bit A;
rand bit [1:0] B;
constraint c_ab {
(A==0) -> B==0;
solve A before B;
}
endclass
2)
class ABSolveBefore;
rand bit A;
rand bit [1:0] B;
constraint c_ab {
(A==0) -> B==0;
solve B before A;
}
endclass
两种情况下,A都能取到0和1,B能取到0123,并且A为0时B都为0。但是求解顺序会导致两者的分布会不一致。如果先求解A再求解B,那么概率分布表为如果先求解B再求解A,那么概率分布表为[221] 什么是mailbox?如何使用mailbox?mailbox是一种通信机制,用于线程之间的数据交换。数据在一个线程存入mailbox中,在另一个线程中检索。下面是mailbox的声明与创建的示例:mailbox mbxRcv;
mbxRcv = new();
将数据存入mailbox中可以使用put(阻塞)和peek(非阻塞)实现,从mailbox中取出数据可以使用get(阻塞)和try_get(非阻塞)方法,查询mailbox中的数据数量可以使用num()方法。[222] 有限容量和无限容量的mailbox有什么区别?如何创建?有限容量的mailbox是指邮箱在创建时就指定容量。mailbox mbxRcv;
mbxRcv = new(10);
//size bounded to 10
无限容量的mailbox是指邮箱再创建时不指定容量。mailbox mbxRcv;
mbxRcv = new();
//size is unbounded or infinite
有限容量的mailbox如果存满,线程将无法继续存入数据,只到mailbox有空间。[223] 什么是systemverilog中的event?如何触发event?event类型的变量不用于存储数据,用于线程同步。可以使用"->"显式触发事件,而线程可以通过"@"来等待事件的触发,阻断线程只到事件被触发。event为两个或者多个同时运行的进程的同步提供强大而有效的手段。下面的示例中,两个线程通过event进行同步。一旦发送请求,send_req()将会触发一个事件,而receive_response()检测到事件被触发以后就会继续执行任务。module test;
event req_send;
initial begin
fork
send_req();
receive_response);
join
end
task send_req();
//create and send a req
-> req_send; //trigger event
endtask
task receive_response();
@req_send; //wait until a send event is triggered
//collect response
endtask
endmodule
[224] 如何合并两个event?可以指将将一个event变量赋值给另一个event变量,此时两个event变量都指向同一个同步对象,可以认为两者合并。[225] 什么是systemverilog中的std::randomize()方法?何时使用它?std::randomize()是作用域随机化函数,无需定义类或者实例化类对象仅能对当前作用域中的数据进行随机化。如果某些需要随机化的变量不是类的成员,则需要使用std::randomize()。下面是一个示例。module stim;
bit [15:0] addr;
bit [31:0] data;
function bit gen_stim();
bit success, rd_wr;
success = std::randomize(addr, data, rd_wr);
return rd_wr ;
endfunction

endmodule
std::randomize()和类的randomize()具有相似的功能,也可以使用约束,下面是一个通过with添加约束的示例。success = std::randomize( addr, data, rd_wr ) with {rd_wr -> addr > 'hFF00;};
[226] 在派生类中可以覆盖基类中的约束嘛?如果可以,如何实现?可以通过使用相同的约束名称在派生类中重写基类定义的约束。下面是一个示例class Base;
rand int a ;
rand int b;
constraint
c_a_b_const {a < b;}
endclass
class
Derived extends Base;
constraint c_a_b_const {a > b;}
endclass
[227] 下面的systemverilog代码的调用有什么问题?function int count_ones ( ref bit [9:0] vec );
for( count_ones = 0; vec != 0; vec = vec >> 1 )
begin
count_ones += vec & 1'b1;
end
endfunction
constraint C1 { length == count_ones( myvec ) ; }
在约束中,不允许调用方向为ref的函数,除非使用“const ref”,这保证函数在内部不会修改参数。[228] 下面两个派生类有什么不同?class Base;
virtual function printA();
endfunction
endclass
1)
class Derived extends Base;
function printA();
//new print implementation
endfunction
endclass
2)
class Derived extends Base;
virtual function printA();
//new print implementation
endfunction
endclass
两者并没有区别,在基类中如果定义了virtual关键字,那么派生类也会继承该属性,无论有没有显式的二次声明。[229] 找出下面代码中的问题(如果有的话)class Packet;
bit [31:0] addr;
endclass
class ErrPacket extends Packet;
bit err;
endclass
module Test;
initial begin
Packet p;
ErrPacket
ep;
ep = new();
p = ep;
$display("packet addr=%h err=%b", p.addr, p.err);
end
endmodule
没有问题,基类句柄可以指向派生类对象,但是反过来是不允许的。[230] 现有下面两个类,请问在示例代码中compute_crc函数的调用顺序是?class Packet; //Base Class
rand bit [31:0] src, dst, data[8]; // Variables
bit [31:0] crc;
virtual function void compute_crc;
crc = src ^ dst ^ data.xor;
endfunction
endclass : Packet
class BadPacket extends Packet;
//Derived class
rand bit bad_crc;
virtual function void compute_crc;
//overriding definition
super.compute_crc();
// Compute good CRC
if (bad_crc) crc = ~crc; // Corrupt the CRC bits
endfunction
endclass : BadPacket
示例Packet pkt;
BadPacket
badPkt;
initial begin
pkt
= new;
pkt.compute_crc; // 1) Which of compute_crc() gets called?
badPkt = new;
badPkt.compute_crc; // 2) Which of compute_crc() gets called?
pkt = badPkt; // Base handle points to ext obj
pkt.compute_crc; // 3) Which of compute_crc() gets called ?
end
调用了基类的compute_crc调用了派生类的compute_crc调用了派生类的compute_crc,虽然使用的是基类的句柄,但是方法定义为虚方法,所以要根据对象的类型进行调用[231] 下面两种代码风格哪种更加好?为什么?1)
for (i=0; i < length*count; i++) begin
a[i] = b[i];
end
2)
l_end = length * count;
for (i=0; i < l_end; i++) begin
a[i] = b[i]
end
2比1更好,在1中,每次迭代都需要计算length*count,2中只需要计算一次[232] 下面的代码有什么错误?class ABC;
local int var;
endclass
class DEF extends ABC;
function new();
var = 10;
endfunction
endclass
变量var具备local关键字,在派生类中是不可用的。[233] 什么是虚接口,何时使用它?虚接口是指向实际结构的变量。他在类中用于提供接口的连接点,通过虚接口可以访问接口中的信号。在下面的示例中,接口bus_if将多个信号整合起来。然后,BusTransactor类中定义了这一接口类型的虚接口,这个虚接口用于访问来自this.b_if的所有驱动或检测。实例化物理接口以后,通过构造函数将句柄传递给BusTransactor类。interface bus_if; // A bus interface
logic req, grant;
logic [7:0] addr, data;
endinterface
class BusTransactor; // Bus transactor class
virtual bus_if bus; // virtual interface of type bus_if
function new( virtual bus_if b_if );
bus = b_if; // initialize the virtual interface
endfunction
task request(); // request the bus
bus.req <= 1'b1;
endtask
task wait_for_bus(); // wait for the bus to be granted
@(posedge bus.grant);
endtask
endclass
module top;
bus_if bif(); // instantiate interfaces, connect signals etc
initial begin
BusTransactor xactor;
xactor = new(bif);
//pass interface to constructor
end
endmodule
[234] 工厂和工厂模式的意思是?在面向对象编程中,工厂是用于创建原型或类的不同对象的方法或函数。不同的类在工厂中注册后,工厂方法可以通过调用相应的构造函数来创建任何已注册类类型的对象。创建对象不直接调用构造函数的模式称为工厂模式。使用基于工厂的对象创建而不是直接调用构造函数,允许在对象创建中使用多态性。这个概念是在UVM (Univers)中实现的。[235] 回调函数(callback)的意义是什么?“回调”是由另一个函数调用的任何函数,它以第一个函数为参数。大多数情况下,当某个“事件”发生时,会调用回调函数。在验证平台中,回调函数很多优点:注入从驱动程序发送的事务错误当一个模拟阶段准备结束时,调用一个函数来关闭所有序列/驱动程序中所有挂起的事务。在一个特定的事件上调用一个覆盖率采样函数。大多数情况下,回调函数是通过将它们注册到一个组件/对象中来实现的,该组件/对象会在某些定义的条件下回调。UVM中的phase_ready_to_end()就是回调函数,它在基类中实现,并注册到UVM_component类中。当当前仿真阶段准备结束时,将调用该函数。因此,用户可以通过覆盖此函数定义来实现需要在仿真阶段结束时执行的任何功能。[236] 什么是DPI调用?DPI是直接编程接口的缩写,它是SystemVerilog和C/C++等外语编程语言之间的接口。DPI允许在接口两边的语言之间直接进行跨语言函数调用。在C语言中实现的函数可以在SystemVerilog中调用(import),在SystemVerilog中实现的函数可以使用DPI层在C语言中调用(export)。DPI支持跨语言边界的function(零时间执行)和task(耗时执行)。SystemVerilog数据类型是惟一能够在任何方向上跨越SystemVerilog和外部语言之间的边界的数据类型。[237]
“DPI import” 和“DPI export”有什么区别?import的DPI函数是用C语言实现并在SystemVerilog代码中调用的函数。export的DPI函数是用SystemVerilog语言实现并导出到C语言的函数,这样就可以从C语言调用它。函数和任务都可以导入或导出。[238] 什么是系统函数?举例说明他们的作用SystemVerilog语言支持许多不同的内置系统任务和函数,通常在任务/函数名称前加上“$”前缀。此外,语言还支持添加用户定义的系统任务和功能。下面是一些系统任务和功能的例子(根据功能分类)。对于完整的列表,可以参考LRM。仿真控制函数 - $finish, $stop, $exit转换函数 - $bitstoreal, $itor, $castbit向量系统函数 - $countones, $onehot, $isunknown安全系统函数 - $error, $fatal, $warning采样值控制函数 - $rose, $fell, $changed断言控制函数 - $asserton, $assertoff
最近做项目需要用到yolo,参考了网上一些代码和文章,记录一下对yolo的理解。yolo核心思想:将整张图作为网络的输入,单个神经网络将图像分割成区域。并且,这个神经网络可以预测每个区域的边界框,以及用该边界框分割区域的概率。这些边界框由预测的概率加权。优势:它在测试时查看整个图像,因此它的预测由图像中的全局信息提供。它可以通过单一网络进行预测,而不像R-CNN这样的系统需要数千张图像,这使得它运行速度非常快。yolo代码理解:在对yolo有了初步的了解之后,我在github上找到了一份yolov3的代码,通过代码理解yolo的执行过程。(代码来自GitHub:https://github.com/xiaochus/YOLOv3)首先,argparse这个模块包的意义需要了解一下,详情见注释。import argparse #Argparse的作用就是为py文件封装好可以选择的参数,使他们更加灵活,丰富。即导入一个模块
parser = argparse.ArgumentParser( description='Yet Another Darknet To Keras Converter.') #parser = argparse.ArgumentParser()的目的是创建一个解析对象
parser.add_argument('config_path', help='Path to Darknet cfg file.') #然向该对象中添加你要关注的命令行参数和选项,每一个add_argument方法对应一个你要关注的参数或选项
_main(parser.parse_args()) #最后调用parse_args()方法进行解析,解析成功之后即可使用
yad2k.py部分的代码感觉不需要过分解读,这部分代码的主要目的就是使用yolo的网络结构配置文件使其转换成keras的.h5文件。如下所示,一些关键的地方写了注释。#! /usr/bin/env python
"""
Reads Darknet53 config and weights and creates Keras model with TF backend.
Currently only supports layers in Darknet53 config.
"""
import argparse #Argparse的作用就是为py文件封装好可以选择的参数,使他们更加灵活,丰富。即导入一个模块
import configparser #ConfigParser模块在python中用来读取配置文件,配置文件的格式可以包含一个或多个节(section), 每个节可以有多个参数(键=值)
import io
import os
from collections import defaultdict
import numpy as np
from keras import backend as K
from keras.layers import (Conv2D, GlobalAveragePooling2D, Input, Reshape,
ZeroPadding2D, UpSampling2D, Activation, Lambda, MaxPooling2D)
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.merge import concatenate, add
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.regularizers import l2
from keras.utils.vis_utils import plot_model as plot
parser = argparse.ArgumentParser( description='Yet Another Darknet To Keras Converter.') #parser = argparse.ArgumentParser()的目的是创建一个解析对象
parser.add_argument('config_path', help='Path to Darknet cfg file.') #然向该对象中添加你要关注的命令行参数和选项,每一个add_argument方法对应一个你要关注的参数或选项
parser.add_argument('weights_path', help='Path to Darknet weights file.')
parser.add_argument('output_path', help='Path to output Keras model file.')
parser.add_argument(
'-p',
'--plot_model',
help='Plot generated Keras model and save as image.',
action='store_true')
parser.add_argument(
'-flcl',
'--fully_convolutional',
help='Model is fully convolutional so set input shape to (None, None, 3). '
'WARNING: This experimental option does not work properly for YOLO_v2.',
action='store_true')
def unique_config_sections(config_file): #转换所有config部分,使其具有唯一名称,并为config解析器的兼容性向配置部分添加惟一后缀。
"""Convert all config sections to have unique names.
Adds unique suffixes to config sections for compability with configparser.
"""
section_counters = defaultdict(int) #defaultdict的作用是当字典里的key不存在但被查找时,返回的不是keyError而是一个默认值,这个默认值是多少根据defaultdict()中的值决定,如defaultdict(int)就表示这个默认值是0
output_stream = io.StringIO() #io.StringIO表示在内存中以io流的方式读写str
with open(config_file) as fin:
for line in fin:
if line.startswith('['):
section = line.strip().strip('[]')
_section = section + '_' + str(section_counters[section])
section_counters[section] += 1
line = line.replace(section, _section)
output_stream.write(line)
output_stream.seek(0) #把文件指针移动到文件开始处
return output_stream
def _main(args):
config_path = os.path.expanduser(args.config_path)
#返回参数,参数中开头的~被替换成user的主目录;如果扩展失败或者参数path不是以~打头,则直接返回参数(path)。
weights_path = os.path.expanduser(args.weights_path)
output_path = os.path.expanduser(args.output_path)
assert config_path.endswith('.cfg'), '{} is not a .cfg file'.format(
config_path) #assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。
assert weights_path.endswith(
'.weights'), '{} is not a .weights file'.format(weights_path)
assert output_path.endswith(
'.h5'), 'output path {} is not a .h5 file'.format(output_path)
output_root = os.path.splitext(output_path)[0]
# Load weights and config.
print('Loading weights.')
weights_file = open(weights_path, 'rb')
weights_header = np.ndarray(
shape=(5, ), dtype='int32', buffer=weights_file.read(20)) #ndarray 是一个多维的数组对象,它有一个特点是同构,即其中所有元素的类型必须相同
print('Weights Header: ', weights_header)
# TODO: Check transpose flag when implementing fully connected layers.
# transpose = (weight_header[0] > 1000) or (weight_header[1] > 1000)
print('Parsing Darknet config.')
unique_config_file = unique_config_sections(config_path)
cfg_parser = configparser.ConfigParser()
cfg_parser.read_file(unique_config_file)
print('Creating Keras model.')
if args.fully_convolutional: #如果模型是全卷积的
image_height, image_width = None, None
else:
image_height = int(cfg_parser['net_0']['height'])
image_width = int(cfg_parser['net_0']['width'])
prev_layer = Input(shape=(image_height, image_width, 3))
all_layers = [prev_layer]
outputs = []
weight_decay = float(cfg_parser['net_0']['decay']
) if 'net_0' in cfg_parser.sections() else 5e-4
count = 0
for section in cfg_parser.sections():
print('Parsing section {}'.format(section))
if section.startswith('convolutional'):
filters = int(cfg_parser[section]['filters'])
size = int(cfg_parser[section]['size'])
stride = int(cfg_parser[section]['stride'])
pad = int(cfg_parser[section]['pad'])
activation = cfg_parser[section]['activation']
batch_normalize = 'batch_normalize' in cfg_parser[section]
# Setting weights.
# Darknet serializes convolutional weights as:
# [bias/beta, [gamma, mean, variance], conv_weights]
prev_layer_shape = K.int_shape(prev_layer)
# TODO: This assumes channel last dim_ordering.
weights_shape = (size, size, prev_layer_shape[-1], filters)
darknet_w_shape = (filters, weights_shape[2], size, size)
weights_size = np.product(weights_shape)
print('conv2d', 'bn'
if batch_normalize else '
', activation, weights_shape)
conv_bias = np.ndarray(
shape=(filters, ),
dtype='float32',
buffer=weights_file.read(filters * 4))
count += filters
if batch_normalize:
bn_weights = np.ndarray(
shape=(3, filters),
dtype='float32',
buffer=weights_file.read(filters * 12))
count += 3 * filters
# TODO: Keras BatchNormalization mistakenly refers to var
# as std.
bn_weight_list = [
bn_weights[0],
# scale gamma
conv_bias,
# shift beta
bn_weights[1],
# running mean
bn_weights[2]
# running var
]
conv_weights = np.ndarray(
shape=darknet_w_shape,
dtype='float32',
buffer=weights_file.read(weights_size * 4))
count += weights_size
# DarkNet conv_weights are serialized Caffe-style:
# (out_dim, in_dim, height, width)
# We would like to set these to Tensorflow order:
# (height, width, in_dim, out_dim)
# TODO: Add check for Theano dim ordering.
conv_weights = np.transpose(conv_weights, [2, 3, 1, 0])
conv_weights = [conv_weights] if batch_normalize else [
conv_weights, conv_bias
]
# Handle activation.
act_fn = None
if activation == 'leaky':
pass
# Add advanced activation later.
elif activation != 'linear':
raise ValueError(
'Unknown activation function `{}` in section {}'.format(
activation, section))
padding = 'same' if pad == 1 and stride == 1 else 'valid'
# Adjust padding model for darknet.
if stride == 2:
prev_layer = ZeroPadding2D(((1, 0), (1, 0)))(prev_layer)
# Create Conv2D layer
conv_layer = (Conv2D(
filters, (size, size),
strides=(stride, stride),
kernel_regularizer=l2(weight_decay),
use_bias=not batch_normalize,
weights=conv_weights,
activation=act_fn,
padding=padding))(prev_layer)
if batch_normalize:
conv_layer = (BatchNormalization(
weights=bn_weight_list))(conv_layer)
prev_layer = conv_layer
if activation == 'linear':
all_layers.append(prev_layer)
elif activation == 'leaky':
act_layer = LeakyReLU(alpha=0.1)(prev_layer)
prev_layer = act_layer
all_layers.append(prev_layer)
elif section.startswith('maxpool'):
size = int(cfg_parser[section]['size'])
stride = int(cfg_parser[section]['stride'])
all_layers.append(
MaxPooling2D(
padding='same',
pool_size=(size, size),
strides=(stride, stride))(prev_layer))
prev_layer = all_layers[-1]
elif section.startswith('avgpool'):
if cfg_parser.items(section) != []:
raise ValueError('{} with params unsupported.'.format(section))
all_layers.append(GlobalAveragePooling2D()(prev_layer))
prev_layer = all_layers[-1]
elif section.startswith('route'):
ids = [int(i) for i in cfg_parser[section]['layers'].split(',')]
if len(ids) == 2:
for i, item in enumerate(ids):
if item != -1:
ids[i] = item + 1
layers = [all_layers[i] for i in ids]
if len(layers) > 1:
print('Concatenating route layers:', layers)
concatenate_layer = concatenate(layers)
all_layers.append(concatenate_layer)
prev_layer = concatenate_layer
else:
skip_layer = layers[0]
# only one layer to route
all_layers.append(skip_layer)
prev_layer = skip_layer
elif section.startswith('shortcut'):
ids = [int(i) for i in cfg_parser[section]['from'].split(',')][0]
activation = cfg_parser[section]['activation']
shortcut = add([all_layers[ids], prev_layer])
if activation == 'linear':
shortcut = Activation('linear')(shortcut)
all_layers.append(shortcut)
prev_layer = all_layers[-1]
elif section.startswith('upsample'):
stride = int(cfg_parser[section]['stride'])
all_layers.append(
UpSampling2D(
size=(stride, stride))(prev_layer))
prev_layer = all_layers[-1]
elif section.startswith('yolo'):
classes = int(cfg_parser[section]['classes'])
# num = int(cfg_parser[section]['num'])
# mask = int(cfg_parser[section]['mask'])
n1, n2 = int(prev_layer.shape[1]), int(prev_layer.shape[2])
n3 = 3
n4 = (4 + 1 + classes)
yolo = Reshape((n1, n2, n3, n4))(prev_layer)
all_layers.append(yolo)
prev_layer = all_layers[-1]
outputs.append(len(all_layers) - 1)
elif (section.startswith('net')):
pass
# Configs not currently handled during model definition.
else:
raise ValueError(
'Unsupported section header type: {}'.format(section))
# Create and save model.
model = Model(inputs=all_layers[0],
outputs=[all_layers[i] for i in outputs])
print(model.summary())
model.save('{}'.format(output_path))
print('Saved Keras model to {}'.format(output_path))
# Check to see if all weights have been read.
remaining_weights = len(weights_file.read()) / 4
weights_file.close()
print('Read {} of {} from Darknet weights.'.format(count, count +
remaining_weights))
if remaining_weights > 0:
print('Warning: {} unused weights'.format(remaining_weights))
plot(model, to_file='{}.png'.format(output_root), show_shapes=True)
print('Saved model plot to {}.png'.format(output_root))
if __name__ == '__main__':
_main(parser.parse_args()) #最后调用parse_args()方法进行解析,解析成功之后即可使用
看yolo_model.py部分的代码看的比较痛苦,需要注意的是下面这个predict函数。 def predict(self, image, shape):
"""Detect the objects with yolo.
# Arguments
image: ndarray, processed input image.
shape: shape of original image.
# Returns
boxes: ndarray, boxes of objects.
classes: ndarray, classes of objects.
scores: ndarray, scores of objects.
"""
outs = self._yolo.predict(image) #这里的predict其实用到的是Keras中model.py对predict的定义。它的作用是为输入样本生成输出预测,输入样本批次处理。
#print("11111111111",outs)
boxes, classes, scores = self._yolo_out(outs, shape)
return boxes, classes, scores
最主要的是demo.py部分的代码,对于不同的项目,也基本这部分代码需要改动,详情见注释,写的很详细。"""Demo for use yolo v3
"""
import os
import time
import cv2
import numpy as np
from model.yolo_model import YOLO
def process_image(img):
"""Resize, reduce and expand image.
# Argument:
img: original image.
# Returns
image: ndarray(64, 64, 3), processed image.
"""
image = cv2.resize(img, (416, 416),
interpolation=cv2.INTER_CUBIC)
#图像缩放函数,将图像缩放至指定大小,image是416x416x3矩阵,其中416和416是指定的图像的宽和高的大小,3指图像的通道为3,这表示处理的是彩色图像
image = np.array(image, dtype='float32') #将图像转化为指定类型的数组
image /= 255. #将图像矩阵转化至0~1之间
image = np.expand_dims(image, axis=0) #np.expand_dims:用于扩展数组的形状,这里axis=0使image矩阵变成1x416x416x3矩阵了
return image
def get_classes(file):
"""Get classes name.
# Argument:
file: classes name for database.
# Returns
class_names: List, classes name.
"""
with open(file) as f:
class_names = f.readlines()
class_names = [c.strip() for c in class_names]
return class_names
def draw(image, boxes, scores, classes, all_classes):
"""Draw the boxes on the image.
# Argument:
image: original image.
boxes: ndarray, boxes of objects.
classes: ndarray, classes of objects.
scores: ndarray, scores of objects.
all_classes: all classes name.
"""
for box, score, cl in zip(boxes, scores, classes):
x, y, w, h = box #x,y用于平行;w,h用于缩放
'''
下面上下左右坐标是怎么得到的其实没有特别理解
'''
top = max(0, np.floor(x + 0.5).astype(int))
left = max(0, np.floor(y + 0.5).astype(int))
right = min(image.shape[1], np.floor(x + w + 0.5).astype(int))
bottom = min(image.shape[0], np.floor(y + h + 0.5).astype(int))
cv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 2) #通过对角线画矩形
cv2.putText(image, '{0} {1:.2f}'.format(all_classes[cl], score),
(top, left - 6),
cv2.FONT_HERSHEY_SIMPLEX,
0.6, (0, 0, 255), 1,
cv2.LINE_AA) #为图片添加文字,其中(top, left - 6)指的是左上角坐标
print('class: {0}, score: {1:.2f}'.format(all_classes[cl], score))
print('box coordinate x,y,w,h: {0}'.format(box))
print()
def detect_image(image, yolo, all_classes):
"""Use yolo v3 to detect images.
# Argument:
image: original image.
yolo: YOLO, yolo model.
all_classes: all classes name.
# Returns:
image: processed image.
"""
pimage = process_image(image)
start = time.time() #测量时钟时间
boxes, classes, scores = yolo.predict(pimage, image.shape)
'''
检测的核心输出,其中
boxes:框的四个点坐标,(top, left, bottom, right);
scores:框的类别置信度,融合框置信度和类别置信度;
classes:框的类别;
'''
end = time.time()
print('time: {0:.2f}s'.format(end - start)) #输出所用时间
if boxes is not None:
draw(image, boxes, scores, classes, all_classes)
return image
def detect_video(video, yolo, all_classes):
"""Use yolo v3 to detect video.
# Argument:
video: video file.
yolo: YOLO, yolo model.
all_classes: all classes name.
"""
video_path = os.path.join("videos", "test", video)
camera = cv2.VideoCapture(video_path)
cv2.namedWindow("detection", cv2.WINDOW_AUTOSIZE)
# Prepare for saving the detected video
sz = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.VideoWriter_fourcc(*'mpeg') #cv2.VideoWriter_fourcc()函数的作用是输入四个字符代码即可得到对应的视频编码器。
vout = cv2.VideoWriter()
vout.open(os.path.join("videos", "res", video), fourcc, 20, sz, True)
while True: #以下代码的作用是在视频中截取图片
res, frame = camera.read()
if not res:
break
image = detect_image(frame, yolo, all_classes)
cv2.imshow("detection", image)
# Save the video frame by frame
vout.write(image)
if cv2.waitKey(110) & 0xff == 27:
break
vout.release()
camera.release()
if __name__ == '__main__':
yolo = YOLO(0.6, 0.5) #0.6和0.5分别表示threshold for object以及threshold for box;就是定义的两个参数
file = 'data/coco_classes.txt'
all_classes = get_classes(file)
# detect images in test floder.
for (root, dirs, files) in os.walk('images/test'): #os.walk返回的(root,dirs,files)分别表示:root 所指的是当前正在遍历的这个文件夹的本身的地址;dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录);files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
if files:
for f in files:
print(f)
path = os.path.join(root, f)
image = cv2.imread(path)
image = detect_image(image, yolo, all_classes)
cv2.imwrite('images/res/' + f, image)
# detect videos one at a time in videos/test folder
video = 'library1.mp4'
detect_video(video, yolo, all_classes)
另外,关于视频部分的yolo处理方法,还需要进一步理解!yolo代码执行过程中出现配置环境问题:主要是之前执行代码时,一直出现“ImportError: Failed to import pydot. You must install pydot and graphviz for pydotprint to work.”这样的错误。对于windows系统+Python3.6+anaconda3的环境,解决方法大致如下:pip install graphviz,先下载graphvizpip install pydot_ng==2.0.0,下载pydot_ng,我的是2.0.0版本,亲测可用。(如果是Python 2,需要下载的是pydot)在这个网址(http://www.graphviz.org/download/ )下载相应graphviz的安装包,即使用pip下载了,也一定要在这个网址再下载一遍!!!经过实验,还是下载msi版本吧,zip版本并没什么用。然后执行msi,我是创建了一个新的文件夹“graphviz-2.38”,然后把执行msi后的文件安装到了这个文件夹中。基本目录如下图所示。把bin文件夹环境添加到系统的环境变量中。我的是“F:\ana\Lib\site-packages\graphviz-2.38\bin”。进行最后测试。如果是Python 3,执行以下代码:import pydot_ng as pydot1
print(pydot1.find_graphviz())
如果是Python 2,执行以下代码:import pydot
print pydot.find_graphviz()
如果最终显示“{‘dot’: ‘F:\ana\Lib\site-packages\graphviz-2.38\bin\dot.exe’, ‘twopi’: ‘F:\ana\Lib\site-packages\graphviz-2.38\bin\twopi.exe’, ‘neato’: ‘F:\ana\Lib\site-packages\graphviz-2.38\bin\neato.exe’, ‘circo’: ‘F:\ana\Lib\site-packages\graphviz-2.38\bin\circo.exe’, ‘fdp’: ‘F:\ana\Lib\site-packages\graphviz-2.38\bin\fdp.exe’, ‘sfdp’: ‘F:\ana\Lib\site-packages\graphviz-2.38\bin\sfdp.exe’}”,那说明编译成功。yolo代码基本可以执行了。

lrm格式文件如何打开哪里有打开这个格式的软件下载呢...
lrm格式文件如何打开哪里有打开这个格式的软件下载呢
展开选择擅长的领域继续答题?
{@each tagList as item}
${item.tagName}
{@/each}
手机回答更方便,互动更有趣,下载APP
提交成功是否继续回答问题?
手机回答更方便,互动更有趣,下载APP
展开全部lrm格式文件为歌曲的歌词内容,可使用电脑中的记事本打开,具体演示操作如下。1、这里,将lrm格式文件发送到电脑桌面,如图。2、在文件上右击鼠标,选择【用记事本打开该文件】。3、然后,就可以查看文件中的内容,示例如图。注意事项:如果手机中带有wps文档软件,可以直接打开,无需发送电脑。已赞过已踩过你对这个回答的评价是?评论
收起
展开全部这个是公务员编辑器生成的文件,需要专门的lrm编辑器才能打开
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询
为你推荐:
下载百度知道APP,抢鲜体验使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。扫描二维码下载
×个人、企业类侵权投诉
违法有害信息,请在下方选择后提交
类别色情低俗
涉嫌违法犯罪
时政信息不实
垃圾广告
低质灌水
我们会通过消息、邮箱等方式尽快将举报结果通知您。说明
做任务开宝箱累计完成0
个任务
10任务
50任务
100任务
200任务
任务列表加载中...

我要回帖

更多关于 win7设备安装被策略阻止 的文章

 

随机推荐