diff --git a/frameworks/boards/verilator/verilator.sh b/frameworks/boards/verilator/verilator.sh index ce6ee438..7035834d 100755 --- a/frameworks/boards/verilator/verilator.sh +++ b/frameworks/boards/verilator/verilator.sh @@ -148,8 +148,8 @@ cd .. if [[ -z "${NO_PROGRAM}" ]]; then rm -f output.txt - ./obj_dir/Vtop | tee out.log - # ./obj_dir/Vtop > out.log 2>&1 + # ./obj_dir/Vtop | tee out.log + ./obj_dir/Vtop > out.log 2>&1 else echo "Skipping execution." fi diff --git a/projects/ice-v/CPUs/ice-v-swirl.si b/projects/ice-v/CPUs/ice-v-swirl.si index 5eb5da71..80b2a40f 100644 --- a/projects/ice-v/CPUs/ice-v-swirl.si +++ b/projects/ice-v/CPUs/ice-v-swirl.si @@ -161,7 +161,7 @@ $$end always { $$if DEBUG_swirl then - uint1 debug_on = (cycle > 40885000); + uint1 debug_on = 0; // (cycle > 40333206) && (cycle < 40339206); $$end // tracks whether a register was written cycle before @@ -379,9 +379,9 @@ $$end } $$if SIMULATION then // check for unaligned loads (unsupported) - if ((exec.load & ~bubble & ~jumping) + if ((exec.load|exec.store) & ~bubble & ~jumping & (exec.op[0,2]==2b10) & (exec.n[0,2] != 2b00)) { - __display("[cycle %d] ERROR @%h %h, unaligned lw from @%h",cycle,pc<<2,instr,exec.n); + __display("[cycle %d] ERROR @%h %h, unaligned access (%b) @%h",cycle,pc<<2,instr,exec.store,exec.n); __finish(); } $$end @@ -519,7 +519,8 @@ if (debug_on) { } $$end $$if TRACE_swirl then - if (trace_on) { + //uint32 full = dmem.addr<<2; + if (trace_on /*|| full[8,16] == 16h14cd*/) { if ((|dmem.wenable) & ~stall_cpu) { __display("store @%x = %x",dmem.addr<<2,dmem.wdata); } diff --git a/projects/ice-v/SOCs/swirl-cache.si b/projects/ice-v/SOCs/swirl-cache.si index cace463c..96a48be1 100644 --- a/projects/ice-v/SOCs/swirl-cache.si +++ b/projects/ice-v/SOCs/swirl-cache.si @@ -59,15 +59,25 @@ interface bram_provider input addr, } -$$cache_line_width = 8 -$$cache_line_size_words = 1< <- num_cache_lines_w -> <----- cache_line_w -----> +// <--------------------------------- ramW --------------------------------> +// ^<-------------------- 14 bits -------------------> +// | +// cache_addr_start +// +$$cache_line_w = 8 -- has to be < 14 +$$cache_line_size = 1 << cache_line_w +$$num_cache_lines_w = (14 - cache_line_w) +$$num_cache_lines = 1 << num_cache_lines_w +$$cache_addr_w = ramW - 14 +$$cache_addr_start = 14 $$print('<> ' .. num_cache_lines -$$ .. ' cache lines of ' .. cache_line_size_words .. ' int32') +$$ .. ' cache lines of ' .. cache_line_size .. ' int32') // -------------------------------------------------- // cache unit @@ -93,7 +103,8 @@ unit cache( // cache for mem1 is spram2,spram3 (2x 16 bits) // // each cache stores 16K x int32 - // thus 2^(14 - cache_line_width) lines of 2^cache_line_width int32 + // thus 2^(14 - cache_line_w) lines of 2^cache_line_w int32 + // $$for n=0,3 do $$if SIMULATION then simulation_spram spram$n$; @@ -108,18 +119,18 @@ $$ init_value = '1' .. init_value $$end $$init_value = (cache_addr_w+1) .. 'b0' .. init_value - // cache mapping + // cache mapping, stores for each line the upper address part, and a dirty bit bram uint$cache_addr_w+1$ cache0_lines[$num_cache_lines$] = {pad($init_value$)}; bram uint$cache_addr_w+1$ cache1_lines[$num_cache_lines$] = {pad($init_value$)}; // ^ dirty bit $$for c=0,1 do // determines whether requested addr match the corresponding cache line - uint$num_cache_lines_w$ line$c$_id <: mem$c$.addr[$cache_line_width$,$num_cache_lines_w$]; - uint1 cache$c$_hit <:: qaddr$c$[$cache_line_width$,$cache_addr_w$] + uint$num_cache_lines_w$ line$c$_id <: mem$c$.addr[$cache_line_w$,$num_cache_lines_w$]; + uint1 cache$c$_hit <:: qaddr$c$[$cache_addr_start$,$cache_addr_w$] == :cache$c$_lines.rdata[0,$cache_addr_w$]; uint1 cache$c$_canwrite <:: (:line$c$_id == qline$c$_id) - && :mem$c$.addr[$cache_line_width$,$cache_addr_w$] + && :mem$c$.addr[$cache_addr_start$,$cache_addr_w$] == :cache$c$_lines.rdata[0,$cache_addr_w$]; // registers for memory interface inputs uint$num_cache_lines_w$ qline$c$_id(0); @@ -149,7 +160,18 @@ $$end uint1 keep_wait(0); uint1 write_fault(0); +$$if SIMULATION then + uint1 debug_on(0); +$$end + always_before { +$$if SIMULATION then + if (mem0.addr[$ramW$,1] || mem1.addr[$ramW$,1]) { + __display("ERROR cache accessed on peripheral address"); + __finish(); + } + debug_on = 0; // (cycle > 40333206) && (cycle < 40339206); +$$end /* __display("[%d] >> cache status in: @%x|@%x q: @%x|@%x miss: %b|%b ln: %x|%x", cycle,mem0.addr<<2,mem1.addr<<2, @@ -172,10 +194,10 @@ $$end // default lookup mem0.rdata = {spram1.data_out,spram0.data_out}; mem1.rdata = {spram3.data_out,spram2.data_out}; - spram0.addr = {line0_id,mem0.addr[0,$cache_line_width$]}; - spram1.addr = {line0_id,mem0.addr[0,$cache_line_width$]}; - spram2.addr = {line1_id,mem1.addr[0,$cache_line_width$]}; - spram3.addr = {line1_id,mem1.addr[0,$cache_line_width$]}; + spram0.addr = {line0_id,mem0.addr[0,$cache_line_w$]}; + spram1.addr = {line0_id,mem0.addr[0,$cache_line_w$]}; + spram2.addr = {line1_id,mem1.addr[0,$cache_line_w$]}; + spram3.addr = {line1_id,mem1.addr[0,$cache_line_w$]}; spram0.wmask = {{2{mem0.wenable[1,1]}},{2{mem0.wenable[0,1]}}}; spram1.wmask = {{2{mem0.wenable[3,1]}},{2{mem0.wenable[2,1]}}}; spram0.wenable = (|mem0.wenable) & cache0_canwrite; @@ -219,7 +241,9 @@ $$end if (update_lines_todo) { // there is a pending cache miss $$if SIMULATION then - __display("[%d] => cache miss %b|%b %x|%x",cycle,~cache0_hit,~cache1_hit,qaddr0<<2,qaddr1<<2); + if (debug_on) { + __display("[%d] => cache miss %b|%b %x|%x",cycle,~cache0_hit,~cache1_hit,qaddr0<<2,qaddr1<<2); + } $$end // if line is dirty, store back // vvvvv start by cache0, then cache1 @@ -228,15 +252,17 @@ $$end if (line_dirty) { // store back line as it was written to uint$ramW$ storeAddr = - ~cache0_hit ? {cache0_lines.rdata,$cache_line_width$b0} - : {cache1_lines.rdata,$cache_line_width$b0}; - uint$cache_line_width+2+1$ n = 0; + ~cache0_hit ? {cache0_lines.rdata[0,$cache_addr_w$],qline0_id,$cache_line_w$b0} + : {cache1_lines.rdata[0,$cache_addr_w$],qline1_id,$cache_line_w$b0}; + uint$cache_line_w+2+1$ n = 0; $$if SIMULATION then - __display("[%d] => [cache %b] writing at @%x from line %d",cycle,cache0_hit,storeAddr,~cache0_hit ? qline0_id : qline1_id); + if (debug_on) { + __display("[%d] => [cache %b] writing at @%x from line %d",cycle,cache0_hit,storeAddr<<2,~cache0_hit ? qline0_id : qline1_id); + } $$end // write start addr ram.addr = {storeAddr,2b00}; - while (~n[$cache_line_width+2$,1]) { + while (~n[$cache_line_w+2$,1]) { // maintain write status ram.in_ready = 1; ram.wenable = 1; @@ -248,16 +274,22 @@ $$end : {spram3.data_out,spram2.data_out} >> {n[0,2],3b0}; // next? if (reg_ram_wstream) { +$$if SIMULATION then + //uint32 full = ram.addr + n; + //if (full[8,16] == 16h14cd || debug_on) { + // __display("store @%x = %x (cache %b, line %d, cycle %d)",full,ram.wdata,cache0_hit,~cache0_hit ? qline0_id : qline1_id,cycle); + //} // __write("%x,",ram.wdata); +$$end // next n = n + 1; } // read in cache 0 - spram0.addr = {qline0_id,n[2,$cache_line_width$]}; - spram1.addr = {qline0_id,n[2,$cache_line_width$]}; + spram0.addr = {qline0_id,n[2,$cache_line_w$]}; + spram1.addr = {qline0_id,n[2,$cache_line_w$]}; // read in cache 1 - spram2.addr = {qline1_id,n[2,$cache_line_width$]}; - spram3.addr = {qline1_id,n[2,$cache_line_width$]}; + spram2.addr = {qline1_id,n[2,$cache_line_w$]}; + spram3.addr = {qline1_id,n[2,$cache_line_w$]}; } // __display(" "); ++: // this one cycle pause is needed before starting to read, otherwise @@ -265,25 +297,27 @@ $$end } // fetch new line uint$ramW$ fetchAddr = - ~cache0_hit ? {qaddr0[$cache_line_width$,$cache_addr_w$], - $cache_line_width$b0} - : {qaddr1[$cache_line_width$,$cache_addr_w$], - $cache_line_width$b0}; - uint$cache_line_width+2+1$ n = 0; + ~cache0_hit ? {qaddr0[$cache_line_w$,$ramW-cache_addr_w$], + $cache_line_w$b0} + : {qaddr1[$cache_line_w$,$ramW-cache_addr_w$], + $cache_line_w$b0}; + uint$cache_line_w+2+1$ n = 0; $$if SIMULATION then - __display("[%d] +> cache miss %b|%b %x|%x",cycle,~cache0_hit,~cache1_hit,qaddr0<<2,qaddr1<<2); - __display("[%d] => [cache %b] fetching from @%x in line %d",cycle,cache0_hit,fetchAddr<<2,~cache0_hit ? qline0_id : qline1_id); + // __display("[%d] +> cache miss %b|%b %x|%x",cycle,~cache0_hit,~cache1_hit,qaddr0<<2,qaddr1<<2); + if (debug_on) { + __display("[%d] => [cache %b] fetching from @%x in line %d",cycle,cache0_hit,fetchAddr<<2,~cache0_hit ? qline0_id : qline1_id); + } $$end ram.addr = {fetchAddr,2b00}; - while (~n[$cache_line_width+2$,1]) { + while (~n[$cache_line_w+2$,1]) { ram.in_ready = 1; if (reg_ram_datanext) { uint4 wmask = 2b11 << {n[0,1],1b0}; uint16 wdata = reg_ram_rdata << {n[0,1],3b0}; // __write("%x,", reg_ram_rdata); // cache 0 - spram0.addr = {qline0_id,n[2,$cache_line_width$]}; - spram1.addr = {qline0_id,n[2,$cache_line_width$]}; + spram0.addr = {qline0_id,n[2,$cache_line_w$]}; + spram1.addr = {qline0_id,n[2,$cache_line_w$]}; spram0.data_in = wdata; spram1.data_in = wdata; spram0.wmask = wmask; @@ -291,8 +325,8 @@ $$end spram0.wenable = ~cache0_hit & ~n[1,1]; spram1.wenable = ~cache0_hit & n[1,1]; // cache 1 - spram2.addr = {qline1_id,n[2,$cache_line_width$]}; - spram3.addr = {qline1_id,n[2,$cache_line_width$]}; + spram2.addr = {qline1_id,n[2,$cache_line_w$]}; + spram3.addr = {qline1_id,n[2,$cache_line_w$]}; spram2.data_in = wdata; spram3.data_in = wdata; spram2.wmask = wmask; @@ -306,10 +340,10 @@ $$end // __display(" "); // update cache register if (~cache0_hit) { - cache0_lines.wdata = {1b0,qaddr0[$cache_line_width$,$cache_addr_w$]}; + cache0_lines.wdata = {1b0,qaddr0[$cache_addr_start$,$cache_addr_w$]}; cache0_lines.wenable = 1; } else { - cache1_lines.wdata = {1b0,qaddr1[$cache_line_width$,$cache_addr_w$]}; + cache1_lines.wdata = {1b0,qaddr1[$cache_addr_start$,$cache_addr_w$]}; cache1_lines.wenable = 1; } keep_wait = 1; // IMPORTANT: keeps wait high during bram transaction @@ -321,7 +355,7 @@ $$end write_cycle = 1; // keeps wait high while write to cache line occurs // TODO: only if indeed writing? $$if SIMULATION then - __display("[%d] cache done.",cycle); + // __display("[%d] cache done.",cycle); $$end } else { // if no cache miss, maintain dirty flag