çè«çãªç解ãæ確ã«ããããã«ãããªãèªèº«ã®éã¡ãããããªãèªèº«ã®èŠãçµéšããåŠã¶ãããè¯ãæ¹æ³ã¯ãããŸããã ïŒããªãŒããªãããšã³ã²ã«ã¹ïŒ
ã¿ãªããããã«ã¡ã¯ïŒ
ååãæ°é±éåã«ãªã³ã¯ã€ã³ã§ç§ã«æçŽãæžããŠãããã·ã¥ããŒãã«ãç§ã®github ãããžã§ã¯ãã§æ£ããæ©èœããªããšèšã£ãã
ãã¹ããšä¿®æ£ãç§ã«éãããã·ã¹ãã ãããã³ã°ãããç¶æ³ãå®éã«äœæãããŸããã åé¡ã調æ»ãããšãæ€èšŒäžã«ããã€ãã®ééããç¯ããããšã«æ°ä»ããŸããã Habrã§ã¯ãRTLã³ãŒãã®æ€èšŒã®ãããã¯ã¯ããŸã詳ããæãããŠããªãã®ã§ãèšäºãæžãããšã«ããŸããã
èšäºãã次ã®ããšãåŠã³ãŸãã
- FPGAã§ããã·ã¥ããŒãã«ãæŽçããã«ã¯ã©ãããã°ããã§ããïŒ
- ã©ã®æ€èšŒãæ§ç¯ããããã«ã€ããŠã
- ç§ãç¯ããééãïŒãã°ã以åã¯æ°ä»ããªãã£ããšããäºå®ã«ã€ãªãã£ãïŒã
- ã©ãããã°ããããã¹ãŠä¿®æ£ã§ããŸããã
ç«ãžããããïŒ
ãããžã§ã¯ãã«ã€ããŠç°¡åã«
ç®æšãšèæ¯
ãããžã§ã¯ãã®éå§åã«èšå®ããç®æšïŒ
- ããã·ã¥ããŒãã«ã«Nåã®èŠçŽ ããããšäž»åŒµãããŠããå Žåãããã«Nåã®èŠçŽ ãåãŸãããšãä¿èšŒãããŸãã
- ããŒãã«èªäœãè¡çªã解決ããããããã¹ã±ããå
ã®èŠçŽ ã®æ°ã«å¶éã¯ãããŸããïŒãã¡ãããããã·ã¥ããŒãã«ã®ãµã€ãºä»¥äžïŒã
- ããŒãã«ã§ã¯ãããŒã«ããè¿œå ãæ€çŽ¢ãåé€ãå¯èœã§ã
- æ€çŽ¢äžã«è¡çªããªãå ŽåãããŒãã«ã¯ã¯ããã¯ãµã€ã¯ã«ããšã«æ€çŽ¢ã¿ã¹ã¯ãåãå
¥ããæºåãã§ããŠããŸãïŒæ倧ããã©ãŒãã³ã¹ïŒã
- ãªãœãŒã¹ãšã¯ããã¯é床ã«ã€ããŠã¯å¿é
ããŸãã ã
å
éšããã€ã¹
æ倧ã®ããã©ãŒãã³ã¹ãåŸããã®ã§ããã€ãã©ã€ã³ãæŽçããŸãã

å
¥åïŒ ht_cmd
ïŒïŒ
typedef enum logic [1:0] { OP_SEARCH, OP_INSERT, OP_DELETE } ht_opcode_t; typedef struct packed { logic [KEY_WIDTH-1:0] key; logic [VALUE_WIDTH-1:0] value; ht_opcode_t opcode; } ht_command_t;
åºåïŒ ht_res
ïŒïŒ
typedef enum int unsigned { SEARCH_FOUND, SEARCH_NOT_SUCCESS_NO_ENTRY, INSERT_SUCCESS, INSERT_SUCCESS_SAME_KEY, INSERT_NOT_SUCCESS_TABLE_IS_FULL, DELETE_SUCCESS, DELETE_NOT_SUCCESS_NO_ENTRY } ht_rescode_t; typedef struct packed { ht_command_t cmd; ht_rescode_t rescode; logic [BUCKET_WIDTH-1:0] bucket;
泚 ïŒ
å®éã found_value
ã§ã¯rescode
ãšfound_value
ã®ã¿ã«é¢å¿ãããfound_value
ããå°ãå
ãèŠãŠããŸããä»ã®ãã£ãŒã«ãããªããšãæ€èšŒããã®ãé£ãããªããŸãã ãšã«ãããããããéã§äœ¿çšãããŠããªãå Žåãã·ã³ã»ãµã€ã¶ãŒã¯ããããåãåãããªãœãŒã¹ãæ¶è²»ããŸããã
äœãã©ãã«ãããïŒ
- ãã¹ãŠã®ããŒã¿ïŒ
key
ã value
ïŒã¯data_table
ä¿åããdata_table
ã - æ
å ±ã¯ããªã³ã¯ãªã¹ããæŽçããããã®ããŒã¿ïŒ
next_ptr
ã next_ptr_val
ïŒã®é£ã«æ ŒçŽãããŸãã - ãã¹ã±ããã®ãªã³ã¯ãªã¹ãã®å
é ãäœçœ®ããã»ã«çªå·ã¯ã
head_table
æ ŒçŽããhead_table
ã empty_ptr_storage
ã¯ã空ã®è¡çªå·ãdata_table
ä¿åãdata_table
ã
head_table
å
ã®head_table
ïŒ
typedef struct packed { logic [HEAD_PTR_WIDTH-1:0] ptr; logic ptr_val; } head_ram_data_t;
data_table
å
ã®åèªïŒ
typedef struct packed { logic [KEY_WIDTH-1:0] key; logic [VALUE_WIDTH-1:0] value; logic [HEAD_PTR_WIDTH-1:0] next_ptr; logic next_ptr_val; } ram_data_t;
æäœã¢ã«ãŽãªãºã ïŒ
calc_hash
ã¯key
ã䜿çšããŠããã·ã¥ãèšç®ããŸãïŒãã®å€ã¯ãã¹ã±ããçªå·ïŒ bucket_num
ïŒã§ãïŒãbucket_num
ã®ã¢ãã¬ã¹ãšããŠhead_table
ã䜿çšããŸãããã¹ã±ããã®ãªã³ã¯ãªã¹ãã®å
é ãžã®ãã€ã³ã¿ãŒãååŸããŸãã- ãã«ããã¬ã¯ãµãŒã¯ãç®çã®ã¢ãžã¥ãŒã«ïŒ
data_table_search
ã data_table_insert
ã data_table_delete
ïŒã«ã¿ã¹ã¯ãé
åžããŸãïŒ opcode
çŠç¹ãåãããŸãïŒã - 察å¿ããã¿ã¹ã¯ïŒ
task
ïŒãå®è¡ïŒfindãinsertãdeleteïŒã®ããã«åãåãã data_table
ããèªã¿æžãããïŒãªã³ã¯ããããªã¹ããå®è¡task
ïŒã¢ãžã¥ãŒã«ã ht_res
ã®çµæãht_res
ãŸãã
èå³æ·±ããã¥ã¢ã³ã¹ïŒ
data_table
ã¡ã¢ãªã«ã¯2ã¯ããã¯ã®èªã¿åãé
延ããããããåã¯ããã¯ãµã€ã¯ã«ãæ€çŽ¢ããããã«ãè€æ°ã®ïŒ5ã€ã®ïŒäžŠåã¢ãžã¥ãŒã«ãäœæãããã¿ã¹ã¯ã¯ã©ãŠã³ãããã³ã«ãã£ãŠåæ£ãããŸãã- 空ãã»ã«ã®æ€çŽ¢ãé«éåããããã«ã
empty_ptr_storage
æäŸãããŠããŸãã å·çæç¹ã§ã¯ãããã¯éåžžã«éåççã«å®è£
ãããŠããŸããããã¯ãã«empty_ptr_mask
ïŒãã®é·ãã¯data_table
ããŒãã«å
ã®ã»ã«ã®æ°ã§ãïŒã«ãããã¬ãžã¹ã¿ã«æ ŒçŽãããŠããŸãã ãŸãã空ã®èŠçŽ ã®æ€çŽ¢ã¯ãïŒçµã¿åããã§ïŒãŒãã¡ãžã£ãŒããç¡å¹åãããããšã«ãã£ãŠè¡ãããŸãã ãªãœãŒã¹ãšé »åºŠã®ç¹ã§ã¯ãããã¯æé©ãªãœãªã¥ãŒã·ã§ã³ã§ã¯ãããŸããã
次ã®ããã«ãªããŸãïŒ ã¯ãªãã¯ããŠæ¡å€§ ïŒïŒ

ãšã©ãŒãåé¿/ãããã°ãç°¡çŽ åããããã«ç§ãããããš
ããã·ã¥ããŒãã«ã®äœæãéå§ããåã«ããããžã§ã¯ããç°¡åã§ã¯ãªãããšãç解ãããããéçºãå éããããã°ãç°¡çŽ åããããã€ãã®ããšãäºåã«äºæž¬ããŸããã
SystemVerilogãšã³ãŒãã£ã³ã°ã¹ã¿ã€ã«
SystemVerilogãšäŒæ¥ã¹ã¿ã€ã«ã®ã³ãŒãã£ã³ã°ãHDLèšèªãšããŠäœ¿çšãããŸããã
ããã«ãããæ§é ãç°¡åã«èšè¿°ãïŒäžèšãåç
§ïŒãç¬èªã®ããŒã¿åãäœæããŠãããšãã°FSMãèšè¿°ããããšãã§ããŸãã
enum int unsigned { IDLE_S, NO_VALID_HEAD_PTR_S, READ_HEAD_S, GO_ON_CHAIN_S, KEY_MATCH_S, ON_TAIL_WITHOUT_MATCH_S } state, next_state;
ã¹ããªãŒãã³ã°ã€ã³ã¿ãŒãã§ã€ã¹ïŒAvalon-STïŒ
ã³ã³ãã¢ãéçºãããšãã¯ããã€åæ¢ããããããç解ããå¿
èŠããããŸãã
å€ãã®ããšãæãã€ãããšãã§ããŸãããæ¢è£œã®éçºãããã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããããšãæåã§ãã
è·å Žã§ã¯ãã¢ã«ãã©ã®FPGAã䜿çšããŠäœæããŠãããããã¢ã«ãã©ã®FPGAãæäŸ/ä¿é²ããã€ã³ã¿ãŒãã§ãŒã¹ã«ç²ŸéããŠããŸãã ãã®ãããžã§ã¯ãã§ã¯ã Avalonãã¡ããªãŒã䜿çšããŸããã
ã³ãã³ãã¯åãªãããŒã¿ã¹ããªãŒã ïŒ1ã¯ãŒãAvalon-Streaming (Avalon-ST)
ã³ãã³ãïŒã§ããããã Avalon-Streaming (Avalon-ST)
æšæºAvalon-Streaming (Avalon-ST)
ïŒ data
ã ready
ã valid
ä¿¡å·ïŒã䜿çšããŸããã
ããã¯ã readyLatency = 0
ïŒ æšæºããååŸ ïŒã®ãšãã®Avalon-ST
äžã®ãã©ã³ã¶ã¯ã·ã§ã³ã®æ§åã§ãã

ãã®å³ã§ã¯ãã¹ã¬ãŒããå¶åŸ¡ããã¬ãã£ä¿¡å·ããã©ã³ã¶ã¯ã·ã§ã³ãšããŒã¿è»¢éãã·ã£ããããŠã³ããŠããããšãããããŸãã
ãããŒããã·ã¥
ãã®ããã·ã¥ããŒãã«ãã©ã®ããã«äœæããã®ãçåã«æã£ããšããæãå°é£ãªããšã¯æ€èšŒããããšã§ããããšã«æ°ä»ããŸããã æããã«ãæãèå³æ·±ããã¥ã¢ã³ã¹ã¯ããã§ã«ããŒã¿ããããã§ãŒã³ã«è¿œå ããããšããããé·ããã§ãŒã³ããåé€ããããããšãã«è¡šç€ºãããŸãã
ããã¯ãã·ã¹ãã ãžã®åœ±é¿ãé©çšããããšãã«ãäºåå®çŸ©ããããã¹ã±ããçªå·ã䜿çšããŠããŒïŒ key
ïŒãç°¡åã«çæã§ããå¿
èŠãããããšãæå³ããŸãã
å®éã®ããã·ã¥é¢æ°ã§ã¯ãããã«ã¯åé¡ãããããã HASH_TYPE
ãã©ã¡ãŒã¿ãŒã®å€ã¯"dummy hash"
çããHASH_TYPE
ãŸãã
ãã®ã¿ã€ãã®ããã·ã¥ãéžæãããŠããå Žåããã¹ã±ããçªå·ã¯åã«ããŒã®äžäœBUCKET_WIDTH
ãããã§ãã
ãããã£ãŠã key = 0x92123456
ã§ã BUCKET_WIDTH
ã8ã®å Žåã bucket_num = 0x92
ã§ãã
ããã«ãããç¹å®ã®å¢çã±ãŒã¹ã®çæã«å¿
èŠãªã¢ã¯ã·ã§ã³ãç°¡åã«äœæã§ããŸãã
ã·ãã¥ã¬ãŒã·ã§ã³ãã®ã³ã°
éçºè
ã¯ã SignalTapãŸãã¯ChipScopeã䜿çšããŠãããŒããŠã§ã¢ïŒèªã¿åããããŒãïŒã§RTLã¢ãžã¥ãŒã«ãçŽæ¥ãããã°ããå ŽåããããŸã ã ãã®ã¢ãããŒãã¯ãåžžã«æéãã€æãçç£çã§ã¯ãããŸãã-ãããžã§ã¯ãå
šäœïŒ10åããæ°æéïŒïŒæã«ã¯è€æ°åïŒãæå
ã®ããŒãããããã¬ãŒãå
¥åã¢ã¯ã·ã§ã³ã®çæãªã©ãåæ§ç¯ããå¿
èŠããããŸãã
éçºãã¹ããŒãã¢ããããããã«ã ModelSim ãVCSãIcarus Verilogãªã©ã®ç¹å¥ãªã·ãã¥ã¬ãŒã¿ãŒã䜿çšãããŸããã¿ã€ã ãã£ãŒãïŒã¿ã€ã ãã¬ãŒã ïŒãæ§ç¯ããããšã«ããããããã°äžã«ãã¹ãŠã®ïŒãŸãã¯éžæãããïŒä¿¡å·/ å€æ°ã®å€ã远跡ã§ããŸãã ãããã®ãã£ãŒãããããã°ããã«ã¯ãèšå€§ãªæéããããå ŽåããããŸãã
解決ç ïŒ
çºçãããã¹ãŠã®ã¢ã¯ã·ã§ã³ããã°ã«èšé²ããç®ãéããŠããã«èŠãããšãã§ããŸãã
ãã®ããã«ã data_table_insert
ã data_table_delete
ã data_table_search
ã«ããã°ã«åºåããé¢æ°ãè¿œå ããŸããã
function void print( string s ); $display("%08t: %m: %s", $time, s); endfunction
display
圢åŒã¯printf
䌌ãŠããŸãïŒ %d
ã %f
ãªã©ã䜿çšã§ããŸãïŒã
%08t
ã·ãã¥ã¬ãŒã·ã§ã³æéã衚瀺ããŸãïŒé©åãªã¿ã€ãã³ã°ã§ãžã£ã³ããããšäŸ¿å©ã§ãïŒã%m
ãããçºçããã¢ãžã¥ãŒã«ïŒéå±€åïŒãåºåããŸãã ïŒæ³šæïŒããã¯åŒæ°ãåããŸããïŒïŒ%s
è¡ãå°å·ããŸã
FSMé·ç§»ã®ãã®ã³ã°ïŒ
function void print_state_transition( ); string msg; if( next_state != state ) begin $sformat( msg, "%s -> %s", state, next_state ); print( msg ); end endfunction
æ°ããã¿ã¹ã¯ã®åä¿¡ãå°å·ããŸãã
function string pdata2str( input ht_pdata_t pdata ); string s; $sformat( s, "opcode = %s key = 0x%x value = 0x%x head_ptr = 0x%x head_ptr_val = 0x%x", pdata.cmd.opcode, pdata.cmd.key, pdata.cmd.value, pdata.head_ptr, pdata.head_ptr_val ); return s; endfunction function void print_new_task( ht_pdata_t pdata ); print( pdata2str( pdata ) ); endfunction
ãªã©ãªã©...
ã·ãã¥ã¬ãŒã·ã§ã³ã«ã¯ãModelSimã䜿çšããŸãã ç»é¢ã«è¡šç€ºããããã°ïŒããã³ããã©ã«ãã§ã¯ã transcript
ãã¡ã€ã«ã«ã¢ã¯ã»ã¹ããŸãïŒã«ã¯ã次ã®è¡ã衚瀺ãããŸãã
1465: top_tb.dut.d_tbl.sea_eng.g_s_eng[3].search.print: opcode = OP_SEARCH key = 0x04000000 value = 0x0000 head_ptr = 0x000 head_ptr_val = 0x0 1465: top_tb.dut.d_tbl.sea_eng.g_s_eng[3].search.print: IDLE_S -> NO_VALID_HEAD_PTR_S 1475: top_tb.dut.d_tbl.sea_eng.g_s_eng[3].search.print: RES: key = 0x04000000 value = 0x0000 rescode = SEARCH_NOT_SUCCESS_NO_ENTRY 1475: top_tb.dut.d_tbl.sea_eng.g_s_eng[3].search.print: NO_VALID_HEAD_PTR_S -> IDLE_S 1475: ht_tb.print: IN_MONITOR: key = 0x04000000 value = 0x0000 rescode = SEARCH_NOT_SUCCESS_NO_ENTRY 1485: top_tb.dut.d_tbl.del_eng.print: opcode = OP_DELETE key = 0x04111111 value = 0x0000 head_ptr = 0x000 head_ptr_val = 0x0 1485: top_tb.dut.d_tbl.del_eng.print: IDLE_S -> NO_VALID_HEAD_PTR_S 1495: top_tb.dut.d_tbl.del_eng.print: RES: key = 0x04111111 value = 0x0000 rescode = DELETE_NOT_SUCCESS_NO_ENTRY 1495: top_tb.dut.d_tbl.del_eng.print: NO_VALID_HEAD_PTR_S -> IDLE_S 1495: ht_tb.print: IN_MONITOR: key = 0x04111111 value = 0x0000 rescode = DELETE_NOT_SUCCESS_NO_ENTRY 1505: top_tb.dut.d_tbl.ins_eng.print: opcode = OP_INSERT key = 0x04000000 value = 0xb95f head_ptr = 0x000 head_ptr_val = 0x0 1505: top_tb.dut.d_tbl.ins_eng.print: IDLE_S -> NO_HEAD_PTR_WR_HEAD_PTR_S 1515: top_tb.dut.h_tbl.print: addr = 0x04 wr_data.ptr = 0x003 wr_data.ptr_val = 0x1 1515: top_tb.dut.d_tbl.ins_eng.print: NO_HEAD_PTR_WR_HEAD_PTR_S -> NO_HEAD_PTR_WR_DATA_S 1525: top_tb.dut.d_tbl.ins_eng.print: WR: addr = 0x003 key = 0x04000000 value = 0xb95f next_ptr = 0x000, next_ptr_val = 0x0 1525: top_tb.dut.d_tbl.ins_eng.print: RES: key = 0x04000000 value = 0xb95f rescode = INSERT_SUCCESS 1525: top_tb.dut.d_tbl.ins_eng.print: NO_HEAD_PTR_WR_DATA_S -> IDLE_S
ãã®ãããªããã¹ããã°ã¯ãgrepãæ€çŽ¢ã®å®è¡ãç°¡åã§ãïŒããšãã°ãvim'eã§ïŒã
ãã°ã¯æéã倧å¹
ã«ç¯çŽããŸãããç°¡åãªäŸãéä¿¡ãããšããã©ã®é åºã§æžãããã¹ãããç¥ã£ãŠããŠããã°ãèŠãã ãã§ããã ãšã©ãŒãçºçããå Žåãã¿ã€ãã³ã°å³ã§ã¯ãªãã³ãŒããåæããŸããã
ãã£ã¬ã³ãžãšããŠãã¿ã€ã ã¢ãŠããªãã§1é±é以å
ã«RTLã³ãŒãããããã°ããããšããå§ãããŸãïŒå¿«é©ãŸãŒã³ãé¢ããïŒã
æ€èšŒ
System Verilog for Verificationãªã©ã®åªããæç®ã«ç®ãåãããšãåªããæ£ãããã¹ããã³ããšããŠæ¬¡ã®å³ããããŸãã

ãã®èšäºã§ã¯ãChris Spearãããã³ãåãäžããã€ããã¯ãªãã®ã§ãããããã¹ãŠã®ã³ã³ããŒãã³ãã®æå³ã«ã€ããŠã¯è©³ãã説æããŸããã
ç§ã®ãã¹ããã³ãã®ã¹ããŒã ïŒ

top_tb
ãããã¢ãžã¥ãŒã«ã
DUTïŒããã€ã¹/ãã¹ã察象èšèšïŒ
ãã¹ã察象ã¯ã hash_table_top
ã¢ãžã¥ãŒã«ã®ã€ã³ã¹ã¿ã³ã¹ã§ãã
ht_driver
- ã¯ã¡ãŒã«ããã¯ã¹
gen2drv
å«ã¿ãŸããããã¯ã³ãã³ããDUT
éãããããã§ãã - ãã®ãã¥ãŒã«ã³ãã³ãã衚瀺ããããšããã«ãã³ãã³ãã¯
DUT
éä¿¡ããDUT
ã - ã³ãã³ãã
DUT
ã«éä¿¡ããåŸãã³ãã³ãã¯ht_scoreboard
ã³ããŒããht_scoreboard
ã
ãã®ã¡ãŒã«ããã¯ã¹ã«ã³ãã³ããé
眮ããã«ã¯ãéå±€ã¢ã¯ã»ã¹ã䜿çšãããŸãã
task send_to_dut_c( input ht_command_t c ); // using hierarchial access to put command in mailbox env.drv.gen2drv.put( c ); endtask
ãã¹ã
ããã©ãŒãã³ã¹ããã¹ãããããã«ã3ã€ã®ãã¹ã/å
¥åã¢ã¯ã·ã§ã³ãäœæãããŸããã
äœæ¥ãç°¡çŽ åãããã¯ãïŒ
`define CMD( _OP, _KEY, _VALUE ) cmds.push_back( '{ opcode : _OP, key : _KEY, value : _VALUE } ); `define CMD_SEARCH( _KEY ) `CMD( OP_SEARCH, _KEY, 0 ) `define CMD_INSERT( _KEY, _VALUE ) `CMD( OP_INSERT, _KEY, _VALUE ) `define CMD_INSERT_RAND( _KEY ) `CMD_INSERT( _KEY, $urandom() ) `define CMD_DELETE( _KEY ) `CMD( OP_DELETE, _KEY, 0 )
ãã¹ãäŸïŒ
task test_01( ); ht_command_t cmds[$]; $display("%m:"); `CMD_INSERT( 32'h01_00_00_00, 16'h1234 ) `CMD_INSERT( 32'h01_00_10_00, 16'h1235 ) `CMD_INSERT_RAND( 32'h01_00_00_00 ) `CMD_INSERT_RAND( 32'h01_00_00_01 ) `CMD_DELETE ( 32'h01_00_00_00 ) `CMD_INSERT_RAND( 32'h01_00_00_02 ) `CMD_SEARCH( 32'h01_00_00_00 ) `CMD_SEARCH( 32'h01_00_00_01 ) `CMD_SEARCH( 32'h01_00_00_01 ) `CMD_SEARCH( 32'h01_00_00_03 ) foreach( cmds[i] ) begin send_to_dut_c( cmds[i] ); end endtask
ht_monitor
ht_res
ã®åºåã€ã³ã¿ãŒãã§ã€ã¹ãç£èŠããŸãã- çµæãåŸããããšããã«
ht_scoreboard
ãã ht_scoreboard
éä¿¡ãht_scoreboard
ã
ht_scoreboard
DUTã®æ£ããåäœã確èªããŸãã
次ã®ãã®ãå«ãŸããŸãã
- 2ã€ã®
mailbox
ãããŒã ã¯ããããht_driver
ãšht_monitor
ã®çµæãå
¥ããŸãã - ããã·ã¥ããŒãã«
ref_hash_table
åç
§ã¢ãã«ã
æäœã¢ã«ãŽãªãºã ïŒ
ht_res
ã®çµæãht_res
ãšããã«ã圌ãšå¯Ÿå¿ãããªã¯ãšã¹ãã¯ãã¥ãŒããåãåºãããŸãã ããã§ãåããŒã ã«çããããã®ã¯ç§ãã¡ã®æã«ãããŸããcheck
é¢æ°ãåŒã³åºãããã³ãã³ããåç
§ã¢ãã«ã«å
¥åãããDUTãšåç
§ã¢ãã«ã®çµæãæ¯èŒãããŸãã- äžèŽãããã®ããªãå Žåã¯ã
$error
ã䜿çšããŠãããã«ã€ããŠãã°ã«ã¡ãã»ãŒãžãåºåãããModelSimã®GUIã«ãããçºçããç¬éã«èµ€ãç¢å°ã衚瀺ãããŸãã
ã«ãã¬ããž
ãã®ãããããŸããŸãªå
¥åã®åœ±é¿ãéä¿¡ããããDUTã®åå¿ã®æ£ç¢ºããåæãããã§ããã·ã¹ãã ïŒå¿
èŠã«å¿ããŠããã¬ãŒã ã¯ãŒã¯ïŒãæ¢ã«ãããŸãã ãã°ããªãããšã確èªããã«ã¯ããå¯èœãªãã¹ãŠã®ããªãã·ã§ã³ãã«ããŒããå¿
èŠããããŸãã
SystemVerilogã¯ãã«ãã¬ããžãè©äŸ¡ããããã«ãcovergroupããã³coverpointãªããžã§ã¯ããå°å
¥ããŸãã ã 圌ãã®å©ããåããŠããµã³ããªã³ã°ããããã€ã³ããšãåéããçµ±èšã説æã§ããŸãã
covergroup cg(); option.per_instance = 1; CMDOP: coverpoint result_locked.cmd.opcode; CMDRES: coverpoint result_locked.rescode; BUCKOCUP: coverpoint bucket_occup[ result_locked.bucket ] { bins zero = { 0 }; bins one = { 1 }; bins two = { 2 }; bins three = { 3 }; bins four = { 4 }; bins other = { [5:$] }; } CMDOP_BUCKOCUP: cross CMDOP, BUCKOCUP; CMDRES_BUCKOCUP: cross CMDRES, BUCKOCUP {
説æïŒ
CMDOP
ãšCMDRES
ã¯ã ht_cmd
æäœãšht_res
çµæht_res
äœã§ãã£ããã远跡ããŸããbucket_occup
é
åã«ã¯ãæäœæã«ãã¹ã±ããã«ãã£ãèŠçŽ ã®æ°ãæ ŒçŽãããŸããCMDOP_BUCKOCUP
ã³ãã³ãããã¹ã±ããå
ã®èŠçŽ ã®æ°ãšã亀差ããããŸããã€ãã³ãã¯Xã³ãã³ãã§ããããã¹ã±ããã§ã¯Yã®èŠçŽ ãååšããkey
å±ããŠããŸãããCMDRES_BUCKOCUP
çµæããã¹ã±ããå
ã®ã¢ã€ãã æ°ãšã CMDRES_BUCKOCUP
ããããŸãã
ã·ãã¥ã¬ãŒã·ã§ã³ã®çµäºåŸãModelSimã³ã³ãœãŒã«ã§ã¬ããŒããååŸã§ããŸãã
coverage save 1.ucdb vcover report 1.ucdb -verbose -cvg
å ±åæžïŒ
COVERGROUP COVERAGE: ---------------------------------------------------------------------------------------------------- Covergroup Metric Goal/ Status At Least ---------------------------------------------------------------------------------------------------- TYPE /top_tb/dut/resm/cg 94.0% 100 Uncovered Coverpoint cg::CMDOP 100.0% 100 Covered Coverpoint cg::CMDRES 85.7% 100 Uncovered Coverpoint cg::BUCKOCUP 100.0% 100 Covered Cross cg::CMDOP_BUCKOCUP 100.0% 100 Covered Cross cg::CMDRES_BUCKOCUP 84.6% 100 Uncovered Covergroup instance \/top_tb/dut/resm/cg1 94.0% 100 Uncovered Coverpoint CMDOP 100.0% 100 Covered covered/total bins: 3 3 missing/total bins: 0 3 bin auto[OP_SEARCH] 21 1 Covered bin auto[OP_INSERT] 21 1 Covered bin auto[OP_DELETE] 18 1 Covered Coverpoint CMDRES 85.7% 100 Uncovered covered/total bins: 6 7 missing/total bins: 1 7 bin auto[SEARCH_FOUND] 12 1 Covered bin auto[SEARCH_NOT_SUCCESS_NO_ENTRY] 9 1 Covered bin auto[INSERT_SUCCESS] 14 1 Covered bin auto[INSERT_SUCCESS_SAME_KEY] 7 1 Covered bin auto[INSERT_NOT_SUCCESS_TABLE_IS_FULL] 0 1 ZERO bin auto[DELETE_SUCCESS] 11 1 Covered bin auto[DELETE_NOT_SUCCESS_NO_ENTRY] 7 1 Covered Coverpoint BUCKOCUP 100.0% 100 Covered covered/total bins: 6 6 missing/total bins: 0 6 bin zero 7 1 Covered bin one 13 1 Covered bin two 9 1 Covered bin three 12 1 Covered bin four 8 1 Covered bin other 11 1 Covered Cross CMDOP_BUCKOCUP 100.0% 100 Covered covered/total bins: 18 18 missing/total bins: 0 18 bin <auto[OP_SEARCH],zero> 1 1 Covered bin <auto[OP_INSERT],zero> 5 1 Covered bin <auto[OP_SEARCH],one> 5 1 Covered ... Cross CMDRES_BUCKOCUP 84.6% 100 Uncovered covered/total bins: 33 39 missing/total bins: 6 39 bin <auto[SEARCH_NOT_SUCCESS_NO_ENTRY],zero> 1 1 Covered bin <auto[INSERT_SUCCESS],zero> 5 1 Covered bin <auto[DELETE_NOT_SUCCESS_NO_ENTRY],zero> 1 1 Covered ...
ãã¹ãŠã®å¯èœãªäº€å·®ç¹ã¯èªåçã«åä¿¡ãããŸãã-ç§ãã¡ã¯äœåãªããšãæžããŸããã§ããã
3ã€ã®ãã¹ãã®åŸã次ã®ããšãæããã«ãªããŸãã
OP_INSERT
ãæ¿å
¥ããã³ãã³ãã21 OP_INSERT
ãåé€ããã³ãã³ãã18åãããŸãã- ãã¹ã±ããã«ã¢ã€ãã ããªãã£ããšãã«äžåºŠã ãæ€çŽ¢ããããšãã
INSERT_NOT_SUCCESS_TABLE_IS_FULL
ã€ãã³ãã¯äžåºŠããªãã£ã
æåŸã«
- åºåãåç
§ã¢ãã«ãšæ¯èŒããããšã«ãããDUTãæ£åžžã«æ©èœããŠãããã©ããã確èªããã·ã¹ãã ããããŸãã
- å
¥åå¹æãçæãããã¹ãã®å°ããªã»ããããããŸãã
- ãã¹ãã®å質ïŒã«ãã¬ããžïŒã«é¢ãããã£ãŒãããã¯ããããŸãã
- ããããŒããã·ã¥ããšãã®ã³ã°ã䜿çšããŠããããã°ãšã·ãã¥ã¬ãŒã·ã§ã³ãäºåã«ç°¡çŽ åããŸããã
ãã°ã¯äœã§ããã
ãã®å¹æãé©çšãããšã次ã®ããšãããããŸããã
`CMD_INSERT_RAND( 32'h05_00_00_00 ) `CMD_INSERT_RAND( 32'h05_00_00_01 ) `CMD_DELETE ( 32'h05_00_00_01 ) `CMD_INSERT_RAND( 32'h05_00_00_02 ) `CMD_INSERT_RAND( 32'h05_00_00_03 )
ããã«ãããããŒ0x05000003
æ¿å
¥ããããšã 0x05000003
ã¢ãžã¥ãŒã«ãããã³ã°ããããšããäºå®ã«ã€ãªãããŸãã
- åžžã«ã¢ãã¬ã¹0x001ããèªã¿åããŸã
- FSM
state
ã¯GO_ON_CHAIN_S
ãã³ã°ãGO_ON_CHAIN_S
ïŒäºåºŠãšçµäºããŸããïŒ

ïŒ ã¯ãªãã¯ããŠæ¡å€§ ïŒ
ãã°ã«æ¬¡ã®ã¡ãã»ãŒãžã衚瀺ãããŸããã
385: top_tb.dut.d_tbl.ins_eng.print: opcode = OP_INSERT key = 0x05000003 value = 0x7e7e head_ptr = 0x000 head_ptr_val = 0x1 385: top_tb.dut.d_tbl.ins_eng.print: IDLE_S -> READ_HEAD_S 415: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x001, next_ptr_val = 0x1 415: top_tb.dut.d_tbl.ins_eng.print: READ_HEAD_S -> GO_ON_CHAIN_S 445: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 475: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 505: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 535: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 ...
å°ããã°ãå·»ãæ»ããŠåæããŸãã èå³ã®ããè¡ïŒ data_table
ã§èªã¿æžããããè¡ïŒã®ã¿ãæäŸããŸããïŒ
75: top_tb.dut.d_tbl.ins_eng.print: opcode = OP_INSERT key = 0x05000000 value = 0x1f62 head_ptr = 0x000 head_ptr_val = 0x0 95: top_tb.dut.d_tbl.ins_eng.print: WR: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x000, next_ptr_val = 0x0 115: top_tb.dut.d_tbl.ins_eng.print: opcode = OP_INSERT key = 0x05000001 value = 0x3ff2 head_ptr = 0x000 head_ptr_val = 0x1 145: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x000, next_ptr_val = 0x0 155: top_tb.dut.d_tbl.ins_eng.print: WR: addr = 0x001 key = 0x05000001 value = 0x3ff2 next_ptr = 0x000, next_ptr_val = 0x0 165: top_tb.dut.d_tbl.ins_eng.print: WR: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x001, next_ptr_val = 0x1 185: top_tb.dut.d_tbl.del_eng.print: opcode = OP_DELETE key = 0x05000001 value = 0x0000 head_ptr = 0x000 head_ptr_val = 0x1 215: top_tb.dut.d_tbl.del_eng.print: RD: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x001, next_ptr_val = 0x1 245: top_tb.dut.d_tbl.del_eng.print: RD: addr = 0x001 key = 0x05000001 value = 0x3ff2 next_ptr = 0x000, next_ptr_val = 0x0 255: top_tb.dut.d_tbl.del_eng.print: WR: addr = 0x001 key = 0x05000001 value = 0x3ff2 next_ptr = 0x000, next_ptr_val = 0x0 265: top_tb.dut.d_tbl.del_eng.print: WR: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x000, next_ptr_val = 0x0 285: top_tb.dut.d_tbl.ins_eng.print: opcode = OP_INSERT key = 0x05000002 value = 0x5429 head_ptr = 0x000 head_ptr_val = 0x1 315: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x001, next_ptr_val = 0x1 345: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x000, next_ptr_val = 0x0 355: top_tb.dut.d_tbl.ins_eng.print: WR: addr = 0x001 key = 0x05000002 value = 0x5429 next_ptr = 0x000, next_ptr_val = 0x0 365: top_tb.dut.d_tbl.ins_eng.print: WR: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 385: top_tb.dut.d_tbl.ins_eng.print: opcode = OP_INSERT key = 0x05000003 value = 0x7e7e head_ptr = 0x000 head_ptr_val = 0x1 415: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x000 key = 0x05000000 value = 0x1f62 next_ptr = 0x001, next_ptr_val = 0x1 445: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 475: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1 505: top_tb.dut.d_tbl.ins_eng.print: RD: addr = 0x001 key = 0x00000000 value = 0x0000 next_ptr = 0x001, next_ptr_val = 0x1
255ã265 nsã®å¥åŠãªã€ãã³ããçºçããç¬éã«æ°ä»ããããããŸãããæåã«ã addr = 0x001
ã1ã€ã®å€ãèšé²ãã次ã«å¥ã®å€ãèšé²ããŸããã
ããã«ããã data_table
ã«èª€ã£ãããŒã¿ãå«ãŸãããšããäºå®ã«ã€ãªãããŸãã
- ã»ã«0x000ã¯ãã»ã«0x001ã«ãã§ãŒã³ã®ç¶ç¶ãããããšã瀺ããŸãïŒ
next_ptr = 0x001
ã next_ptr_val = 0x1
ïŒ - ã»ã«0x001ã¯ããŒ0x00000000ãä¿åããŸãã ãã¹ã±ãã0x05ã«å
¥ããããšã¯ã§ããŸããããªããªãã ã·ãã¥ã¬ãŒã·ã§ã³ã§ã¯
dummy hash
䜿çšãdummy hash
ã
ããŒ0x05000002ãè¿œå ãããšãèå³æ·±ãç¶æ³ãçºçããŸãã1ã€ã®ã»ã«0x001ã§èšé²ã2åçºçããŸãã
- 355 nsã§èšé²ãããšãæ°ããå€ãèšé²ãããŸãã
empty_ptr_storage
ã¢ãžã¥ãŒã«empty_ptr_storage
ã0x001ã空ã§ããããšãempty_ptr_storage
ãïŒãã®ã¢ãžã¥ãŒã«ã®ã¢ã«ãŽãªãºã ãã空ãšèŠãªãããæå°ã®ã¢ãã¬ã¹ãæäŸããããã«ãªã£ãããšã¯å¹žéã§ãïŒ - 365 nsã«æžã蟌ããšããã§ãŒã³ã®åã®ã»ã«ã§ããã»ã«ãæŽæ°ãããã¢ãžã¥ãŒã«ã«ãããš0x001ã«ãªããŸãã ãã®çµæã0x001ã¯0x001ãæãããã«ãªããŸããã
ããŒ0x05000003ãè¿œå ããããšãããšããã§ãŒã³ãééãããšãã«ã«ãŒããçºçããŸãã 445 nsããã¯ããã§ãŒã³ã«æ²¿ã£ãŠç¡éã«å®è¡ããåãã¢ãã¬ã¹ãèªã¿åããŸãã
ééãã¯äœã§ããã
æããã«ãããŒã¿ãåé€ããã¢ãžã¥ãŒã«ïŒ data_table_delete
ïŒã«ãã£ãŠãšã©ãŒãçºçããŸãã
255 nsã®æç¹ã§ã next_ptr_val
ã»ã«ã®next_ptr_valãã©ã°ããŒãã«èšå®ãã265 nsã®æç¹ã§0x001ã«æžã蟌ãã§ãã¹ãŠã®ãŒããæžã蟌ãå¿
èŠããããŸããã ãã®ããããã®ã¢ãžã¥ãŒã«ã®ã³ãŒãã§æ³å®ãããŠããŸããããããã¯ãèŠãŠã®ãšãããèµ·ãããŸããã§ããã
äºå®ããã§ãŒã³ã®æåŸããèªã¿åãrd_addr
ãšrd_data
ãå¥ã
ã«ä¿åããrd_addr
ãã£ããããäœæ¥ããã°ããã®å€ã䜿çšããŸããã
ãã®ãããªãšã©ãŒïŒ1ã¯ããã¯ãµã€ã¯ã«ã«ããäœåãªé
延ãééã£ãæéã«äžæžããããããŒã¿ãªã©ïŒã¯ãRTLã³ãŒãã§ã¯éåžžã«äžè¬çã§ãã 圌ãã¯ããŸãé¢å¿ãè¡šããŠããªãã®ã§ããã®èšäºã§ã¯ç¹ã«èª¬æããŸããã
ã©ã®ãããªééãããã£ããïŒéçºäžïŒ
ãããžã§ã¯ã管çã¯ãäžå®å
šãã§ã
äºå®ã¯ãç§ãæ³åããããã«ãããžã§ã¯ããè«ççãªçµããã«è³ããªãã£ããšããããšã§ãã ãªã-ä»ã¯èŠããŠããªãã
ããšãã°ã README
ã§ã¯ããããžã§ã¯ãã¯ãã®ã¢ãžã¥ãŒã«ãã©ãã§ã©ã®ããã«äœ¿çšããããã¹ãããããã瀺ããŠããŸããã
2ã€ã®ãã¬ãŒãºãæ¯èŒããŸãã
- ãã®ãããžã§ã¯ãã¯ã 100Gã¹ã€ããã®å®çšŒåã§äœ¿çšãããŸãã
- ãã®ãããžã§ã¯ãã¯æ°é±éã«ããã£ãŠæ¥œãã¿ã®ããã«æžãããŸãã
ããŒã«çŒ¶ ããããžã¥ãŒã¹ã
é±æ«ã«ãã®ã¢ãžã¥ãŒã«ãæžããŠãã©ãã«ãåã蟌ãŸãªãã£ãããšãæ確ã«ç€ºããŠããå ŽåããµãŒãããŒãã£ã®éçºè
ã¯ç§ã®ã¢ãžã¥ãŒã«ã䜿çšãããæéãç¯çŽã§ããªãã£ãã§ãããïŒãã ãããã°ãããããšã¯ããããŸããïŒ ããã®èšäºã¯èªã¿ãŸããïŒã
åé¡ãã³ãŒãå
ã®ã©ãã«ããããprev_rd_addr
ãå§ãããšããåé¡ãprev_rd_addr
å€æ°ã«ããããšãããã£ããšããåæºããŸããã å€ãå²ãåœãŠããããããã¯ã¯æ¬¡ã®ããã«ãªããŸãã
always_ff @( posedge clk_i or posedge rst_i ) if( rst_i ) prev_rd_addr <= '0; else if( rd_en_o )
説æã®ãªãFIXME
ã¯æªãã§ãã åé¡ã説æããããã®äœåãª5åéã¯ãå°æ¥çã«åžžã«ææãäžããŸãã
* çµè« ïŒ
- ãªãŒãã³ãœãŒã¹ã«äœããæçš¿ããå Žåã¯ãããŒããŠã§ã¢ã§ãã¹ãããæ¹æ³ãšå Žæãæ瀺çã«ç€ºããŸãïŒãã¹ãããå ŽåïŒã ãã¹ããããŠããªãå Žåã¯ãæ瀺çã«èšè¿°ããŠãã ããã
- åç¬ã§ãããžã§ã¯ããå®æœããŠããå Žåã¯ã誰ãïŒãããããelectronix.ruãªã©ïŒã«ã³ãŒãã®ã¬ãã¥ãŒãäŸé ŒããŠãã ããã , - , .
- , (, ), ,
KNOWN_PROBLEMS
/ KNOWN_BUGS
Coverage
, , , :
:
ht_chain_state_t
, , :
typedef enum int unsigned { NO_CHAIN, IN_HEAD, IN_MIDDLE, IN_TAIL, IN_TAIL_NO_MATCH } ht_chain_state_t;
. data_table_delete
:
ht_chain_state_t chain_state; always_ff @( posedge clk_i or posedge rst_i ) if( rst_i ) chain_state <= NO_CHAIN; else if( state != next_state ) begin case( next_state ) NO_VALID_HEAD_PTR_S : chain_state <= NO_CHAIN; IN_TAIL_WITHOUT_MATCH_S : chain_state <= IN_TAIL_NO_MATCH; KEY_MATCH_IN_HEAD_S : chain_state <= IN_HEAD; KEY_MATCH_IN_MIDDLE_S : chain_state <= IN_MIDDLE; KEY_MATCH_IN_TAIL_S : chain_state <= IN_TAIL; // no default: just keep old value endcase end // , ```ht_res_monitor``` assign result_o.chain_state = chain_state;
ht_res_monitor
:
// ht_result_t result_history [HISTORY_DELAY:1]; always_ff @( posedge clk_i ) begin if( result_locked_val ) begin result_history[1] <= result_locked; for( int i = 2; i <= HISTORY_DELAY; i++ ) begin result_history[i] <= result_history[i-1]; end end end // 1 , (bucket) logic [HISTORY_DELAY:1] bucket_hist_mask; always_comb begin for( int i = 1; i <= HISTORY_DELAY; i++ ) bucket_hist_mask[i] = ( result_history[i].bucket == result_locked.bucket ); end
covergroup:
... CMDOP_D1: coverpoint result_history[1].cmd.opcode; CMDOP_D2: coverpoint result_history[2].cmd.opcode; CMDRES_D1: coverpoint result_history[1].rescode; CMDRES_D2: coverpoint result_history[2].rescode; CHAIN: coverpoint result_locked.chain_state; BUCK_HIST_MASK: coverpoint bucket_hist_mask; CMDOP_HISTORY_D2: cross CMDOP_D2, CMDOP_D1, CMDOP, BUCK_HIST_MASK; CMDRES_HISTORY_D2: cross CMDRES_D2, CMDRES_D1, CMDRES, BUCK_HIST_MASK { ignore_bins not_check_now = binsof( CMDRES ) intersect{ INSERT_NOT_SUCCESS_TABLE_IS_FULL } || binsof( CMDRES_D1 ) intersect{ INSERT_NOT_SUCCESS_TABLE_IS_FULL } || binsof( CMDRES_D2 ) intersect{ INSERT_NOT_SUCCESS_TABLE_IS_FULL }; } CMDOP_CHAIN: cross CMDOP, CHAIN { ignore_bins insert_in_middle = binsof( CMDOP ) intersect { OP_INSERT } && binsof( CHAIN ) intersect { IN_MIDDLE }; ignore_bins insert_in_tail_no_match = binsof( CMDOP ) intersect { OP_INSERT } && binsof( CHAIN ) intersect { IN_TAIL_NO_MATCH }; }
, bin CMDOP_HISTORY_D2
:
bin <auto[OP_DELETE],auto[OP_SEARCH],auto[OP_SEARCH],auto['b10]>
, :
OP_SEARCH
,OP_SEARCH
,OP_DELETE
,
. :
Coverpoint cg::CMDOP 100.0% 100 Covered Coverpoint cg::CMDRES 85.7% 100 Uncovered Coverpoint cg::CMDOP_D1 100.0% 100 Covered Coverpoint cg::CMDOP_D2 100.0% 100 Covered Coverpoint cg::CMDRES_D1 85.7% 100 Uncovered Coverpoint cg::CMDRES_D2 85.7% 100 Uncovered Coverpoint cg::CHAIN 100.0% 100 Covered Coverpoint cg::BUCK_HIST_MASK 100.0% 100 Covered Coverpoint cg::BUCKOCUP 100.0% 100 Covered Cross cg::CMDOP_BUCKOCUP 100.0% 100 Covered Cross cg::CMDRES_BUCKOCUP 84.6% 100 Uncovered Cross cg::CMDOP_HISTORY_D2 18.5% 100 Uncovered covered/total bins: 20 108 missing/total bins: 88 108 Cross cg::CMDRES_HISTORY_D2 3.1% 100 Uncovered covered/total bins: 27 864 missing/total bins: 837 864 Cross cg::CMDOP_CHAIN 84.6% 100 Uncovered
( , .. )
, HISTORY
(18.5% 3.1%). , , .
, ?
. , , , , 100% .
â . , ( 5 6 ).
:
- coverage . , . , .
- , .
- RTL, ( ), . bin' .
, .
. â . , : Constrained Random Verification .
, , - , - ( ) , , .
, :
function bit [KEY_WIDTH-1:0] gen_rand_key( int min_bucket_num = 0, int max_bucket_num = ( 2**BUCKET_WIDTH - 1 ), int max_key_value = ( 2**( KEY_WIDTH - BUCKET_WIDTH ) - 1 ) ); bit [BUCKET_WIDTH-1:0] bucket_num; bit [KEY_WIDTH-1:0] gen_key; if( hash_table::HASH_TYPE != "dummy" ) begin $display("%m: hash_type = %s not supported here!", hash_table::HASH_TYPE ); $fatal(); end bucket_num = $urandom_range( max_bucket_num, min_bucket_num ); gen_key = $urandom_range( max_key_value, 0 ); // replace high bits by bucket_num (is needs in dummy hash) gen_key[ KEY_WIDTH - 1 : KEY_WIDTH - BUCKET_WIDTH ] = bucket_num; return gen_key; endfunction
[0;15]
[0;7]
.
// testing small amount of buckets with random commands task test_05( ); ht_command_t cmds[$]; $display("%m:"); for( int c = 0; c < 5000; c++ ) begin `CMD_SEARCH ( gen_rand_key( 0, 15, 7 ) ) `CMD_INSERT_RAND ( gen_rand_key( 0, 15, 7 ) ) `CMD_DELETE ( gen_rand_key( 0, 15, 7 ) ) end // , :) cmds.shuffle( ); foreach( cmds[i] ) begin send_to_dut_c( cmds[i] ); end endtask
:
Cross cg::CMDOP_HISTORY_D2 98.1% 100 Uncovered covered/total bins: 106 108 missing/total bins: 2 108 Cross cg::CMDRES_HISTORY_D2 81.1% 100 Uncovered covered/total bins: 701 864 missing/total bins: 163 864
, bin' , , :
// testing only one bucket with random commands task test_06( ); ht_command_t cmds[$]; $display("%m:"); for( int c = 0; c < 1000; c++ ) begin `CMD_SEARCH ( gen_rand_key( 0, 0, 7 ) ) `CMD_INSERT_RAND( gen_rand_key( 0, 0, 7 ) ) `CMD_DELETE ( gen_rand_key( 0, 0, 7 ) ) end cmds.shuffle( ); foreach( cmds[i] ) begin send_to_dut_c( cmds[i] ); end endtask
çµæïŒ
Cross cg::CMDOP_HISTORY_D2 100.0% 100 Covered covered/total bins: 108 108 missing/total bins: 0 108 Cross cg::CMDRES_HISTORY_D2 99.1% 100 Uncovered covered/total bins: 857 864 missing/total bins: 7 864
, ( , rescode=INSERT_NOT_SUCCESS_TABLE_IS_FULL
)
泚 ïŒ
:
""
, .
( ht_res
), "" , . . .
( ) â () .
:
head_table
data_table
empty_ptr_storage
, - .
( ) , /.
, :
head_table
:
data_table
:
key
/next_ptr_val
,- , (
head_table
, - ) - ,
empty_ptr_storage
:
:
tables_monitor
, head_table
, data_table
, empty_ptr
.
, , . .
:
... 1195: top_tb.dut.d_tbl.del_eng.print: opcode = OP_DELETE key = 0x01000000 value = 0x0000 head_ptr = 0x001 head_ptr_val = 0x1 1195: top_tb.dut.d_tbl.del_eng.print: IDLE_S -> READ_HEAD_S 1225: top_tb.dut.d_tbl.del_eng.print: RD: addr = 0x001 key = 0x01001000 value = 0x1235 next_ptr = 0x002 next_ptr_val = 0x1 1225: top_tb.dut.d_tbl.del_eng.print: READ_HEAD_S -> GO_ON_CHAIN_S 1255: top_tb.dut.d_tbl.del_eng.print: RD: addr = 0x002 key = 0x01000001 value = 0x3ff2 next_ptr = 0x000 next_ptr_val = 0x1 1285: top_tb.dut.d_tbl.del_eng.print: RD: addr = 0x000 key = 0x01000002 value = 0x5429 next_ptr = 0x004 next_ptr_val = 0x1 1315: top_tb.dut.d_tbl.del_eng.print: RD: addr = 0x004 key = 0x01000000 value = 0x1cc0 next_ptr = 0x000 next_ptr_val = 0x0 1315: top_tb.dut.d_tbl.del_eng.print: GO_ON_CHAIN_S -> KEY_MATCH_IN_TAIL_S 1325: top_tb.dut.d_tbl.del_eng.print: WR: addr = 0x004 key = 0x01000000 value = 0x1cc0 next_ptr = 0x000 next_ptr_val = 0x0 1325: top_tb.dut.d_tbl.del_eng.print: KEY_MATCH_IN_TAIL_S -> CLEAR_RAM_AND_PTR_S 1335: top_tb.dut.d_tbl.del_eng.print: WR: addr = 0x004 key = 0x00000000 value = 0x0000 next_ptr = 0x000 next_ptr_val = 0x0 1335: top_tb.dut.d_tbl.del_eng.print: RES: key = 0x01000000 value = 0x0000 rescode = DELETE_SUCCESS chain_state = IN_TAIL 1335: top_tb.dut.d_tbl.del_eng.print: CLEAR_RAM_AND_PTR_S -> IDLE_S 1335: ht_tb.print: IN_MONITOR: key = 0x01000000 value = 0x0000 rescode = DELETE_SUCCESS chain_state = IN_TAIL 1335: top_tb.dut.d_tbl.empty_ptr_storage.print: add_empty_ptr: 0x004 ** Error: ERROR: addr = 0x004. This addr is empty, but ptr is val Time: 1340 ns Scope: top_tb.tm.check_one_addr File: ../tb/tables_monitor.sv Line: 119 ** Error: ERROR: addr = 0x004 key=0x00000000 don't match bucket_num = 0x01 Time: 1340 ns Scope: top_tb.tm.check_one_addr File: ../tb/tables_monitor.sv Line: 127
, ( )!
:
- 0x004, , , .. 1335 .
- 0x004
key = 0x00000000
, 0x01 (.. dummy hash ).
:
ãããã«
, , . ( )
IP- ASIC/FPGA -.
:
, . , , .
, RTL-, .
, RTL- :)
ãæž
èŽããããšãããããŸããïŒ .
PSïŒ
.
, :
- ,
systemverilog
? GitHub Flavored Markdown ... spoiler
, markdown?