Feb 5, 2014 开始,今天上到lesson 4. 一共有9个lesson 后面更精彩。加油下周前学完。
前3节课主要是熟悉specman E语言(cadence专用)syntax,语法,api,以及一个packet router的verification code设计。
第四节开始讲这门课的意义在于functoinal verification而不是语言,这个E相对于systemVerilog就像python,是简单语言,不用定义一堆reg,wire,interface。而是关注信号的开始结束和emit,TCM。
这里也有个很不错的带例子的specman E教程网站:点击打开链接
这个是router 的 protocal:
这个是specman E code for router verifiaction:
<'
type packet_length_t : [SHORT, LONG, MEDIUM, RANDOM];
struct packet_s {
// HEADER
// address
address : uint(bits:2);
// address constraint
keep soft address < 3;
// length - 6 bits - max: 64
length : uint(bits:6);
// length constraint
keep min_length is length > 0;
// packet length type constraints
packet_length : packet_length_t;
keep short_packet is (packet_length == SHORT ) => length <= 15;
keep long_packet is (packet_length == LONG ) => length >= 48;
keep medium_packet is (packet_length == MEDIUM) => (length < 48 && length > 15);
// PAYLOAD
payload [length] : list of byte;
// PARITY
parity : byte;
keep parity_proper is parity == calculate_parity(address, length, payload);
// methods
calculate_parity(address: byte(bits:2), length:byte(bits:6), data: list of byte): byte is {
result = %{length, address};
for each (d) in data {
result = result ^ d;
};
};
}
'>
<'
type router_port_t: [OUT0=0,OUT1=1,OUT2=2,IN];
unit packet_receiver_u {
port_name: router_port_t;
clk_p: in simple_port of bit is instance;
keep clk_p.hdl_path() == "clock";
event clock_f is fall(clk_p$)@sim;
suspend_p: out simple_port of bit is instance;
keep suspend_p.hdl_path() == append("suspend_i_",port_name.as_a(uint));
valid_p: in simple_port of bit is instance;
keep valid_p.hdl_path() == append("valid_o_",port_name.as_a(uint));
!response_delay: uint;
keep soft response_delay in [0..500];
respond()@clock_f is {
while TRUE {
sync true(valid_p$ == 1);
gen response_delay;
wait [response_delay];
suspend_p$ = 0;
while (valid_p$ == 1) {
wait [1];
};
suspend_p$ = 1;
};
};
run() is {
start respond();
};
};
'>
<'
import packet;
unit packet_driver_u {
clk_p: in simple_port of bit is instance;
keep clk_p.hdl_path() == "clock";
event clock_f is fall(clk_p$)@sim;
data_p: out simple_port of byte is instance;
keep data_p.hdl_path() == "data_i";
valid_p: out simple_port of bit is instance;
keep valid_p.hdl_path() == "valid_i";
suspend_p: in simple_port of bit is instance;
keep suspend_p.hdl_path() == "suspend_o";
packets_to_send: list of packet_s;
keep soft packets_to_send.size() == 10;
send_pkt(in_pkt: packet_s) @clock_f is {
var lob: list of byte;
lob.add(%{in_pkt.length,in_pkt.address});
lob.add(in_pkt.payload);
lob.add(in_pkt.parity);
for each (pkt_byte) in lob {
sync true(suspend_p$ == 0);
data_p$ = pkt_byte;
if ( (index+1) < lob.size() ) {
valid_p$ = 1;
} else {
valid_p$ = 0;
};
wait [1];
};
};
send_packets() @clock_f is {
for each (pkt) in packets_to_send {
send_pkt(pkt);
};
wait [15];
stop_run();
};
run() is {
start send_packets();
};
};
'>
GUIDANCE
- constrain the packet_driver and packet_receiver to
achieve a specific traffic scenario (details below)
<'
import unit3/e/router_import;