提交 a8373f31 编写于 作者: L Lingrui98

Merge remote-tracking branch 'origin/debian-gogogo' into ifu-timing

......@@ -11,6 +11,8 @@ if __name__ == "__main__":
lines = []
line_count = 0
synthesis_nest_level = 0
reg_init_nest_level = 0
mem_init_nest_level = 0
with open(input_file) as f:
for line in f:
line_count += 1
......@@ -18,30 +20,72 @@ if __name__ == "__main__":
ifdef = re.compile('`ifdef')
ifndef = re.compile('`ifndef')
endif = re.compile('`endif')
# remove the line coverage results of not synthesizable code(mostly assert and fwrite)
synthesis = re.compile('`ifndef SYNTHESIS')
line_coverage = re.compile('^\s*([%]?\d+)\s+if')
# remove the coverage results of random init variables
reg_init = re.compile('`ifdef RANDOMIZE_REG_INIT')
mem_init = re.compile('`ifdef RANDOMIZE_MEM_INIT')
coverage = re.compile('^\s*(%?\d+)\s+')
ifdef_match = ifdef.search(line)
ifndef_match = ifndef.search(line)
endif_match = endif.search(line)
synthesis_match = synthesis.search(line)
line_coverage_match = line_coverage.search(line)
reg_init_match = reg_init.search(line)
mem_init_match = mem_init.search(line)
coverage_match = coverage.search(line)
# enter synthesis block
if synthesis_match:
assert synthesis_nest_level == 0, "Should not nest SYNTHESIS macro"
synthesis_nest_level = 1
if ifdef_match or (ifndef_match and not synthesis_match):
synthesis_nest_level += 1
if endif_match:
synthesis_nest_level -= 1
assert synthesis_nest_level >= 0, "Macro nest level should be >= 0"
if synthesis_nest_level > 0:
if ifdef_match or (ifndef_match and not synthesis_match):
synthesis_nest_level += 1
if endif_match:
synthesis_nest_level -= 1
assert synthesis_nest_level >= 0, "Macro nest level should be >= 0"
# remove line coverage results in systhesis block
if coverage_match:
coverage_stat = coverage_match.group(1)
line = line.replace(coverage_match.group(1), " " * len(coverage_stat))
# enter reg_init block
if reg_init_match:
assert reg_init_nest_level == 0, "Should not nest reg_init macro"
reg_init_nest_level = 1
if reg_init_nest_level > 0:
if (ifdef_match and not reg_init_match) or ifndef_match:
reg_init_nest_level += 1
if endif_match:
reg_init_nest_level -= 1
assert reg_init_nest_level >= 0, "Macro nest level should be >= 0"
# remove line coverage results in systhesis block
if coverage_match:
coverage_stat = coverage_match.group(1)
line = line.replace(coverage_match.group(1), " " * len(coverage_stat))
# enter mem_init block
if mem_init_match:
assert mem_init_nest_level == 0, "Should not nest mem_init macro"
mem_init_nest_level = 1
if mem_init_nest_level > 0:
if (ifdef_match and not mem_init_match) or ifndef_match:
mem_init_nest_level += 1
if endif_match:
mem_init_nest_level -= 1
assert mem_init_nest_level >= 0, "Macro nest level should be >= 0"
# remove line coverage results in systhesis block
if synthesis_nest_level > 0 and line_coverage_match:
coverage_stat = line_coverage_match.group(1)
line = line.replace(line_coverage_match.group(1), " " * len(coverage_stat))
# remove line coverage results in systhesis block
if coverage_match:
coverage_stat = coverage_match.group(1)
line = line.replace(coverage_match.group(1), " " * len(coverage_stat))
lines += line
......
......@@ -5,19 +5,31 @@ import re
import copy
import pprint
COVERRED = "COVERRED"
NOT_COVERRED = "NOT_COVERRED"
LINE_COVERRED = "LINE_COVERRED"
NOT_LINE_COVERRED = "NOT_LINE_COVERRED"
TOGGLE_COVERRED = "TOGGLE_COVERRED"
NOT_TOGGLE_COVERRED = "NOT_TOGGLE_COVERRED"
DONTCARE = "DONTCARE"
BEGIN = "BEGIN"
END = "END"
CHILDREN = "CHILDREN"
MODULE = "MODULE"
INSTANCE = "INSTANCE"
TYPE="TYPE"
ROOT="ROOT"
NODE="NODE"
SELFCOVERAGE="SELFCOVERAGE"
TREECOVERAGE="TREECOVERAGE"
TYPE = "TYPE"
ROOT = "ROOT"
NODE = "NODE"
SELFCOVERAGE = "SELFCOVERAGE"
TREECOVERAGE = "TREECOVERAGE"
LINECOVERAGE = 0
TOGGLECOVERAGE = 1
def check_one_hot(l):
cnt = 0
for e in l:
if e:
cnt += 1
return cnt <= 1
def get_lines(input_file):
lines = []
......@@ -31,41 +43,85 @@ def get_line_annotation(lines):
# pattern_1: 040192 if(array_0_MPORT_en & array_0_MPORT_mask) begin
# pattern_2: 2218110 end else if (_T_30) begin // @[Conditional.scala 40:58]
# pattern_2: 000417 end else begin
coverred_pattern_1 = re.compile('^\s*(\d+)\s+if')
coverred_pattern_2 = re.compile('^\s*(\d+)\s+end else')
not_coverred_pattern_1 = re.compile('^\s*(%0+)\s+if')
not_coverred_pattern_2 = re.compile('^\s*(%0+)\s+end else')
line_coverred_pattern_1 = re.compile('^\s*(\d+)\s+if')
line_coverred_pattern_2 = re.compile('^\s*(\d+)\s+end else')
not_line_coverred_pattern_1 = re.compile('^\s*(%0+)\s+if')
not_line_coverred_pattern_2 = re.compile('^\s*(%0+)\s+end else')
toggle_coverred_pattern_1 = re.compile('^\s*(\d+)\s+reg')
toggle_coverred_pattern_2 = re.compile('^\s*(\d+)\s+wire')
toggle_coverred_pattern_3 = re.compile('^\s*(\d+)\s+input')
toggle_coverred_pattern_4 = re.compile('^\s*(\d+)\s+output')
not_toggle_coverred_pattern_1 = re.compile('^\s*(%0+)\s+reg')
not_toggle_coverred_pattern_2 = re.compile('^\s*(%0+)\s+wire')
not_toggle_coverred_pattern_3 = re.compile('^\s*(%0+)\s+input')
not_toggle_coverred_pattern_4 = re.compile('^\s*(%0+)\s+output')
line_cnt = 0
for line in lines:
coverred_match = coverred_pattern_1.search(line) or coverred_pattern_2.search(line)
not_coverred_match = not_coverred_pattern_1.search(line) or not_coverred_pattern_2.search(line)
line_coverred_match = line_coverred_pattern_1.search(line) or line_coverred_pattern_2.search(line)
not_line_coverred_match = not_line_coverred_pattern_1.search(line) or not_line_coverred_pattern_2.search(line)
assert not (line_coverred_match and not_line_coverred_match)
assert not (coverred_match and not_coverred_match)
toggle_coverred_match = toggle_coverred_pattern_1.search(line) or toggle_coverred_pattern_2.search(line) or \
toggle_coverred_pattern_3.search(line) or toggle_coverred_pattern_4.search(line)
not_toggle_coverred_match = not_toggle_coverred_pattern_1.search(line) or not_toggle_coverred_pattern_2.search(line) or \
not_toggle_coverred_pattern_3.search(line) or not_toggle_coverred_pattern_4.search(line)
assert not (toggle_coverred_match and not_toggle_coverred_match)
if coverred_match:
line_annotations.append(COVERRED)
elif not_coverred_match:
line_annotations.append(NOT_COVERRED)
all_match = (line_coverred_match, not_line_coverred_match,
toggle_coverred_match, not_toggle_coverred_match)
if not check_one_hot(all_match):
print("not_one_hot")
print(line_cnt)
print(all_match)
assert False, "This line matches multiple patterns"
if line_coverred_match:
line_annotations.append(LINE_COVERRED)
elif not_line_coverred_match:
line_annotations.append(NOT_LINE_COVERRED)
elif toggle_coverred_match:
line_annotations.append(TOGGLE_COVERRED)
elif not_toggle_coverred_match:
line_annotations.append(NOT_TOGGLE_COVERRED)
else:
line_annotations.append(DONTCARE)
line_cnt += 1
return line_annotations
# get the line coverage statistics in line range [start, end)
def get_coverage_statistics(line_annotations, start, end):
coverred = 0
not_coverred = 0
line_coverred = 0
not_line_coverred = 0
toggle_coverred = 0
not_toggle_coverred = 0
for i in range(start, end):
if line_annotations[i] == COVERRED:
coverred += 1
if line_annotations[i] == LINE_COVERRED:
line_coverred += 1
if line_annotations[i] == NOT_LINE_COVERRED:
not_line_coverred += 1
if line_annotations[i] == TOGGLE_COVERRED:
toggle_coverred += 1
if line_annotations[i] == NOT_COVERRED:
not_coverred += 1
if line_annotations[i] == NOT_TOGGLE_COVERRED:
not_toggle_coverred += 1
# deal with divide by zero
coverage = 1.0
if coverred + not_coverred != 0:
coverage = float(coverred) / (coverred + not_coverred)
return (coverred, not_coverred, coverage)
line_coverage = 1.0
if line_coverred + not_line_coverred != 0:
line_coverage = float(line_coverred) / (line_coverred + not_line_coverred)
toggle_coverage = 1.0
if toggle_coverred + not_toggle_coverred != 0:
toggle_coverage = float(toggle_coverred) / (toggle_coverred + not_toggle_coverred)
return ((line_coverred, not_line_coverred, line_coverage),
(toggle_coverred, not_toggle_coverred, toggle_coverage))
# get modules and all it's submodules
def get_modules(lines):
......@@ -140,18 +196,26 @@ def get_tree_coverage(modules, coverage):
if CHILDREN not in modules[module]:
modules[module][TREECOVERAGE] = self_coverage
else:
coverred = self_coverage[0]
not_coverred = self_coverage[1]
line_coverred = self_coverage[LINECOVERAGE][0]
not_line_coverred = self_coverage[LINECOVERAGE][1]
toggle_coverred = self_coverage[TOGGLECOVERAGE][0]
not_toggle_coverred = self_coverage[TOGGLECOVERAGE][1]
# the dfs part
for child in modules[module][CHILDREN]:
child_coverage = dfs(child[MODULE])
coverred += child_coverage[0]
not_coverred += child_coverage[1]
line_coverred += child_coverage[LINECOVERAGE][0]
not_line_coverred += child_coverage[LINECOVERAGE][1]
toggle_coverred += child_coverage[TOGGLECOVERAGE][0]
not_toggle_coverred += child_coverage[TOGGLECOVERAGE][1]
# deal with divide by zero
coverage = 1.0
if coverred + not_coverred != 0:
coverage = float(coverred) / (coverred + not_coverred)
modules[module][TREECOVERAGE] = (coverred, not_coverred, coverage)
line_coverage = 1.0
if line_coverred + not_line_coverred != 0:
line_coverage = float(line_coverred) / (line_coverred + not_line_coverred)
toggle_coverage = 1.0
if toggle_coverred + not_toggle_coverred != 0:
toggle_coverage = float(toggle_coverred) / (toggle_coverred + not_toggle_coverred)
modules[module][TREECOVERAGE] = ((line_coverred, not_line_coverred, line_coverage),
(toggle_coverred, not_toggle_coverred, toggle_coverage))
return modules[module][TREECOVERAGE]
for module in modules:
......@@ -163,8 +227,8 @@ def get_tree_coverage(modules, coverage):
# arg1: tree coverage results
# arg2: coverage type
def sort_coverage(coverage, coverage_type):
l = [(module, coverage[module][coverage_type])for module in coverage]
def sort_coverage(coverage, self_or_tree, coverage_type):
l = [(module, coverage[module][self_or_tree][coverage_type])for module in coverage]
l.sort(key=lambda x:x[1][2])
return l
......@@ -174,10 +238,15 @@ def print_tree_coverage(tree_coverage):
tree = tree_coverage[module][TREECOVERAGE]
self = tree_coverage[module][SELFCOVERAGE]
print(" " * level + "- " + module)
print(" " * level + " tree", end="")
print("(%d, %d, %.2f)" % (tree[0], tree[1], tree[2] * 100.0))
print(" " * level + " self", end="")
print("(%d, %d, %.2f)" % (self[0], self[1], self[2] * 100.0))
print(" " * level + " tree_line", end="")
print("(%d, %d, %.2f)" % (tree[LINECOVERAGE][0], tree[LINECOVERAGE][1], tree[LINECOVERAGE][2] * 100.0))
print(" " * level + " self_line", end="")
print("(%d, %d, %.2f)" % (self[LINECOVERAGE][0], self[LINECOVERAGE][1], self[LINECOVERAGE][2] * 100.0))
print(" " * level + " tree_toggle", end="")
print("(%d, %d, %.2f)" % (tree[TOGGLECOVERAGE][0], tree[TOGGLECOVERAGE][1], tree[TOGGLECOVERAGE][2] * 100.0))
print(" " * level + " self_toggle", end="")
print("(%d, %d, %.2f)" % (self[TOGGLECOVERAGE][0], self[TOGGLECOVERAGE][1], self[TOGGLECOVERAGE][2] * 100.0))
# print children nodes
if CHILDREN in modules[module]:
......@@ -215,11 +284,15 @@ if __name__ == "__main__":
# print("tree_coverage:")
# pp.pprint(tree_coverage)
print("SelfCoverage:")
pp.pprint(sort_coverage(tree_coverage, SELFCOVERAGE))
print("LineSelfCoverage:")
pp.pprint(sort_coverage(tree_coverage, SELFCOVERAGE, LINECOVERAGE))
print("LineTreeCoverage:")
pp.pprint(sort_coverage(tree_coverage, TREECOVERAGE, LINECOVERAGE))
print("TreeCoverage:")
pp.pprint(sort_coverage(tree_coverage, TREECOVERAGE))
print("ToggleSelfCoverage:")
pp.pprint(sort_coverage(tree_coverage, SELFCOVERAGE, TOGGLECOVERAGE))
print("ToggleTreeCoverage:")
pp.pprint(sort_coverage(tree_coverage, TREECOVERAGE, TOGGLECOVERAGE))
print("AllCoverage:")
print_tree_coverage(tree_coverage)
package utils
import chisel3._
import chisel3.util._
class DataModuleTemplate[T <: Data](gen: T, numEntries: Int, numRead: Int, numWrite: Int, useBitVec: Boolean = false) extends Module {
val io = IO(new Bundle {
val raddr = Vec(numRead, Input(UInt(log2Up(numEntries).W)))
val rdata = Vec(numRead, Output(gen))
val wen = Vec(numWrite, Input(Bool()))
val waddr = Vec(numWrite, Input(UInt(log2Up(numEntries).W)))
val wdata = Vec(numWrite, Input(gen))
})
val data = Mem(numEntries, gen)
// read ports
for (i <- 0 until numRead) {
io.rdata(i) := data(io.raddr(i))
}
if (useBitVec) {
// waddr_dec(i)(j): waddr(i) is target at entry(j)
val waddr_dec = VecInit(io.waddr.map(UIntToOH(_)(numEntries - 1, 0)))
// waddr_dec_with_en(i)(j): entry(j) is written by io.wdata(i)
val waddr_dec_with_en = VecInit(io.wen.zip(waddr_dec).map{case (en, addr) => Fill(numEntries, en) & addr})
val wen_dec = VecInit((0 until numEntries).map(j => {
val data_wen = VecInit(waddr_dec_with_en.map(en => en(j)))
data_wen.suggestName(s"data_wen_$j")
data_wen.asUInt.orR
}))
val wdata_dec = VecInit((0 until numEntries).map(j =>
waddr_dec_with_en.zip(io.wdata).map{ case (en, data) => Fill(gen.getWidth, en(j)) & data.asUInt}.reduce(_ | _).asTypeOf(gen)
))
waddr_dec.suggestName("waddr_dec")
waddr_dec_with_en.suggestName("waddr_dec_with_en")
wen_dec.suggestName("wen_dec")
wdata_dec.suggestName("wdata_dec")
// write ports
for (i <- 0 until numEntries) {
when (wen_dec(i)) {
data(i) := wdata_dec(i)
}
}
}
else {
// below is the write ports (with priorities)
for (i <- 0 until numWrite) {
when (io.wen(i)) {
data(io.waddr(i)) := io.wdata(i)
}
}
}
// DataModuleTemplate should not be used when there're any write conflicts
for (i <- 0 until numWrite) {
for (j <- i+1 until numWrite) {
assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j)))
}
}
}
......@@ -31,7 +31,7 @@ class DebugIdentityNode()(implicit p: Parameters) extends LazyModule {
}
)
}
debug(in, true)
debug(in, false)
}
}
......
......@@ -6,6 +6,7 @@ import chisel3.util._
object PipelineConnect {
def apply[T <: Data](left: DecoupledIO[T], right: DecoupledIO[T], rightOutFire: Bool, isFlush: Bool) = {
val valid = RegInit(false.B)
valid.suggestName("pipeline_valid")
when (rightOutFire) { valid := false.B }
when (left.valid && right.ready) { valid := true.B }
when (isFlush) { valid := false.B }
......
package utils
import chisel3._
import chisel3.util._
import freechips.rocketchip.tilelink.TLMessages._
import freechips.rocketchip.tilelink.TLPermissions._
import freechips.rocketchip.tilelink.{TLBundle, TLBundleA, TLBundleB, TLBundleC, TLBundleD, TLBundleE, TLChannel}
import xiangshan.HasXSLog
trait HasTLDump { this: HasXSLog =>
trait HasTLDump {
this: HasXSLog =>
implicit class TLDump(channel: TLChannel) {
def dump = channel match {
case a: TLBundleA =>
printChannelA(a)
case b: TLBundleB =>
printChannelB(b)
case c: TLBundleC =>
printChannelC(c)
case d: TLBundleD =>
printChannelD(d)
case e: TLBundleE =>
printChannelE(e)
}
}
def printChannelA(a: TLBundleA): Unit = {
switch(a.opcode) {
is(PutFullData) {
XSDebug(false, true.B,
a.channelName + " opcode: %x param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.opcode, a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
a.channelName + " PutFullData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
case b: TLBundleB =>
}
is(PutPartialData) {
XSDebug(false, true.B,
b.channelName + " opcode: %x param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.opcode, b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
a.channelName + " PutPartialData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
case c: TLBundleC =>
}
is(ArithmeticData) {
XSDebug(false, true.B,
c.channelName + " opcode: %x param: %x size: %x source: %d address: %x data: %x corrupt: %b\n",
c.opcode, c.param, c.size, c.source, c.address, c.data, c.corrupt
a.channelName + " ArithmeticData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
case d: TLBundleD =>
}
is(LogicalData) {
XSDebug(false, true.B,
d.channelName + " opcode: %x param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.opcode, d.param, d.size, d.source, d.sink, d.denied, d.data, d.corrupt
a.channelName + " LogicalData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
case e: TLBundleE =>
XSDebug(false, true.B, e.channelName + " sink: %d\n", e.sink)
}
is(Get) {
XSDebug(false, true.B,
a.channelName + " Get param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
is(Hint) {
XSDebug(false, true.B,
a.channelName + " Intent param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.param, a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
is(AcquireBlock) {
switch(a.param) {
is(NtoB) {
XSDebug(false, true.B,
a.channelName + " AcquireBlock NtoB size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
is(NtoT) {
XSDebug(false, true.B,
a.channelName + " AcquireBlock NtoT size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
is(BtoT) {
XSDebug(false, true.B,
a.channelName + " AcquireBlock BtoT size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
}
}
is(AcquirePerm) {
switch(a.param) {
is(NtoB) {
XSDebug(false, true.B,
a.channelName + " AcquirePerm NtoB size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
is(NtoT) {
XSDebug(false, true.B,
a.channelName + " AcquirePerm NtoT size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
is(BtoT) {
XSDebug(false, true.B,
a.channelName + " AcquirePerm BtoT size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
a.size, a.source, a.address, a.mask, a.data, a.corrupt
)
}
}
}
}
}
def printChannelB(b: TLBundleB): Unit = {
switch(b.opcode) {
is(PutFullData) {
XSDebug(false, true.B,
b.channelName + " PutFullData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(PutPartialData) {
XSDebug(false, true.B,
b.channelName + " PutPartialData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(ArithmeticData) {
XSDebug(false, true.B,
b.channelName + " ArithmeticData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(LogicalData) {
XSDebug(false, true.B,
b.channelName + " LogicalData param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(Get) {
XSDebug(false, true.B,
b.channelName + " Get param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(Hint) {
XSDebug(false, true.B,
b.channelName + " Intent param: %x size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.param, b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(Probe) {
switch(b.param) {
is(toN) {
XSDebug(false, true.B,
b.channelName + " Probe toN size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(toB) {
XSDebug(false, true.B,
b.channelName + " Probe toB size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
is(toT) {
XSDebug(false, true.B,
b.channelName + " Probe toT size: %x source: %d address: %x mask: %x data: %x corrupt: %b\n",
b.size, b.source, b.address, b.mask, b.data, b.corrupt
)
}
}
}
}
}
def printChannelC(c: TLBundleC): Unit = {
switch(c.opcode) {
is(AccessAck) {
XSDebug(false, true.B,
c.channelName + " AccessAck param: %x size: %x source: %d address: %x data: %x corrupt: %b\n",
c.param, c.size, c.source, c.address, c.data, c.corrupt
)
}
is(AccessAckData) {
XSDebug(false, true.B,
c.channelName + " AccessAckData param: %x size: %x source: %d address: %x data: %x corrupt: %b\n",
c.param, c.size, c.source, c.address, c.data, c.corrupt
)
}
is(HintAck) {
XSDebug(false, true.B,
c.channelName + " HintAck param: %x size: %x source: %d address: %x data: %x corrupt: %b\n",
c.param, c.size, c.source, c.address, c.data, c.corrupt
)
}
is(ProbeAck) {
switch(c.param) {
is(TtoB) {
XSDebug(false, true.B,
c.channelName + " ProbeAck TtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoN) {
XSDebug(false, true.B,
c.channelName + " ProbeAck TtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoN) {
XSDebug(false, true.B,
c.channelName + " ProbeAck BtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoT) {
XSDebug(false, true.B,
c.channelName + " ProbeAck TtoT size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoB) {
XSDebug(false, true.B,
c.channelName + " ProbeAck BtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(NtoN) {
XSDebug(false, true.B,
c.channelName + " ProbeAck NtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
}
}
is(ProbeAckData) {
switch(c.param) {
is(TtoB) {
XSDebug(false, true.B,
c.channelName + " ProbeAckData TtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoN) {
XSDebug(false, true.B,
c.channelName + " ProbeAckData TtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoN) {
XSDebug(false, true.B,
c.channelName + " ProbeAckData BtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoT) {
XSDebug(false, true.B,
c.channelName + " ProbeAckData TtoT size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoB) {
XSDebug(false, true.B,
c.channelName + " ProbeAckData BtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(NtoN) {
XSDebug(false, true.B,
c.channelName + " ProbeAckData NtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
}
}
is(Release) {
switch(c.param) {
is(TtoB) {
XSDebug(false, true.B,
c.channelName + " Release TtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoN) {
XSDebug(false, true.B,
c.channelName + " Release TtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoN) {
XSDebug(false, true.B,
c.channelName + " Release BtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoT) {
XSDebug(false, true.B,
c.channelName + " Release TtoT size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoB) {
XSDebug(false, true.B,
c.channelName + " Release BtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(NtoN) {
XSDebug(false, true.B,
c.channelName + " Release NtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
}
}
is(ReleaseData) {
switch(c.param) {
is(TtoB) {
XSDebug(false, true.B,
c.channelName + " ReleaseData TtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoN) {
XSDebug(false, true.B,
c.channelName + " ReleaseData TtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoN) {
XSDebug(false, true.B,
c.channelName + " ReleaseData BtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(TtoT) {
XSDebug(false, true.B,
c.channelName + " ReleaseData TtoT size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(BtoB) {
XSDebug(false, true.B,
c.channelName + " ReleaseData BtoB size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
is(NtoN) {
XSDebug(false, true.B,
c.channelName + " ReleaseData NtoN size: %x source: %d address: %x data: %x corrupt: %b\n",
c.size, c.source, c.address, c.data, c.corrupt
)
}
}
}
}
}
def printChannelD(d: TLBundleD): Unit = {
switch(d.opcode) {
is(AccessAck) {
XSDebug(false, true.B,
d.channelName + " AccessAck param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.param, d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(AccessAckData) {
XSDebug(false, true.B,
d.channelName + " AccessAckData param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.param, d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(HintAck) {
XSDebug(false, true.B,
d.channelName + " HintAck param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.param, d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(Grant) {
switch(d.param) {
is(toT) {
XSDebug(false, true.B,
d.channelName + " Grant toT size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(toB) {
XSDebug(false, true.B,
d.channelName + " Grant toB size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(toN) {
XSDebug(false, true.B,
d.channelName + " Grant toN size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
}
}
is(GrantData) {
switch(d.param) {
is(toT) {
XSDebug(false, true.B,
d.channelName + " GrantData toT size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(toB) {
XSDebug(false, true.B,
d.channelName + " GrantData toB size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
is(toN) {
XSDebug(false, true.B,
d.channelName + " GrantData toN size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
}
}
is(ReleaseAck) {
XSDebug(false, true.B,
d.channelName + " ReleaseAck param: %x size: %x source: %d sink: %d denied: %b data: %x corrupt: %b\n",
d.param, d.size, d.source, d.sink, d.denied, d.data, d.corrupt
)
}
}
}
def printChannelE(e: TLBundleE): Unit = {
XSDebug(false, true.B, e.channelName + "GrantAck sink: %d\n", e.sink)
}
}
......@@ -20,7 +20,6 @@ class DispatchQueueIO(enqnum: Int, deqnum: Int) extends XSBundle {
// dispatch queue: accepts at most enqnum uops from dispatch1 and dispatches deqnum uops at every clock cycle
class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with HasCircularQueuePtrHelper {
val io = IO(new DispatchQueueIO(enqnum, deqnum))
val indexWidth = log2Ceil(size)
val s_invalid :: s_valid:: Nil = Enum(2)
......@@ -34,10 +33,12 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
// tail: first invalid entry (free entry)
val tailPtr = RegInit(VecInit((0 until enqnum).map(_.U.asTypeOf(new CircularQueuePtr(size)))))
val tailPtrMask = UIntToMask(tailPtr(0).value, size)
// valid entries counter
val validCounter = RegInit(0.U(log2Ceil(size + 1).W))
val allowEnqueue = RegInit(true.B)
val validEntries = distanceBetween(tailPtr(0), headPtr(0))
val isTrueEmpty = ~Cat((0 until size).map(i => stateEntries(i) === s_valid)).orR
val canEnqueue = validEntries <= (size - enqnum).U
val canEnqueue = allowEnqueue
val canActualEnqueue = canEnqueue && !io.redirect.valid
/**
......@@ -93,7 +94,8 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
*/
// dequeue
val numDeqTry = Mux(validEntries > deqnum.U, deqnum.U, validEntries)
val currentValidCounter = distanceBetween(tailPtr(0), headPtr(0))
val numDeqTry = Mux(currentValidCounter > deqnum.U, deqnum.U, currentValidCounter)
val numDeqFire = PriorityEncoder(io.deq.zipWithIndex.map{case (deq, i) =>
// For dequeue, the first entry should never be s_invalid
// Otherwise, there should be a redirect and tail walks back
......@@ -146,6 +148,28 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
)
}
// update valid counter and allowEnqueue reg
validCounter := Mux(exceptionValid,
0.U,
Mux(io.redirect.valid,
validCounter,
Mux(lastLastCycleMisprediction,
currentValidCounter,
validCounter + numEnq - numDeq)
)
)
allowEnqueue := Mux(io.redirect.valid,
false.B,
Mux(lastLastCycleMisprediction,
currentValidCounter <= (size - enqnum).U,
// To optimize timing, we don't use numDeq here.
// It affects cases when validCount + numEnq - numDeq <= (size - enqnum).U.
// For example, there're 10 empty entries with 6 enqueue and 2 dequeue.
// However, since dispatch queue size > (numEnq + numDeq),
// even if we allow enqueue, they cannot be dispatched immediately.
validCounter + numEnq <= (size - enqnum).U
)
)
/**
* Part 3: set output and input
......
......@@ -140,6 +140,7 @@ class DivSqrt extends FPUSubModule {
// 53 + 2 + 2 = 57 bits are needed, but 57 % log2(4) != 0, use 58 bits instead
val mantDivSqrt = Module(new MantDivSqrt(D_MANT_WIDTH+2+2+1))
mantDivSqrt.io.kill := kill
mantDivSqrt.io.out.ready := true.B
mantDivSqrt.io.in.valid := state === s_start
mantDivSqrt.io.in.bits.a := Mux(isDivReg || aIsOddExp, Cat(aMantReg, 0.U(5.W)), Cat(0.U(1.W), aMantReg, 0.U(4.W)))
......
......@@ -11,6 +11,7 @@ class MantDivSqrt(len: Int) extends Module{
val a, b = UInt(len.W)
val isDiv = Bool()
}))
val kill = Input(Bool())
val out = DecoupledIO(new Bundle() {
val quotient = UInt(len.W)
val isZeroRem = Bool()
......@@ -45,6 +46,7 @@ class MantDivSqrt(len: Int) extends Module{
when(io.out.fire()){ state := s_idle }
}
}
when(io.kill){ state := s_idle }
val ws, wc = Reg(UInt((len+4).W))
......
......@@ -501,11 +501,11 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
} .otherwise {
when (sfence.bits.rs2) {
// specific leaf of addr && all asid
tlbv := tlbv & ~UIntToOH(sfence.bits.addr(log2Up(TlbL2EntrySize)-1+offLen, 0+offLen))
tlbg := tlbg & ~UIntToOH(sfence.bits.addr(log2Up(TlbL2EntrySize)-1+offLen, 0+offLen))
tlbv := tlbv & ~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
tlbg := tlbg & ~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
} .otherwise {
// specific leaf of addr && specific asid
tlbv := tlbv & (~UIntToOH(sfence.bits.addr(log2Up(TlbL2EntrySize)-1+offLen, 0+offLen)) | tlbg)
tlbv := tlbv & (~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))| tlbg)
}
}
}
......
......@@ -127,7 +127,7 @@ class IFU extends XSModule with HasIFUConst
val if1_npc = WireInit(0.U(VAddrBits.W))
val if2_ready = WireInit(false.B)
val if2_allReady = WireInit(if2_ready && icache.io.req.ready)
val if1_fire = if1_valid && (if2_allReady || if1_flush)
val if1_fire = if1_valid && (if2_allReady || if2_flush)
// val if2_newPtr, if3_newPtr, if4_newPtr = Wire(UInt(log2Up(ExtHistoryLength).W))
......@@ -401,7 +401,7 @@ class IFU extends XSModule with HasIFUConst
if1_npc := npcGen()
icache.io.req.valid := if1_valid && (if2_ready || if1_flush)
icache.io.req.valid := if1_valid && (if2_ready || if2_flush)
icache.io.resp.ready := if4_ready
icache.io.req.bits.addr := if1_npc
icache.io.req.bits.mask := mask(if1_npc)
......
......@@ -62,6 +62,9 @@ class LoadQueue extends XSModule with HasDCacheParameters with HasCircularQueueP
val enqPtrExt = RegInit(VecInit((0 until RenameWidth).map(_.U.asTypeOf(new LqPtr))))
val deqPtrExt = RegInit(0.U.asTypeOf(new LqPtr))
val validCounter = RegInit(0.U(log2Ceil(LoadQueueSize + 1).W))
val allowEnqueue = RegInit(true.B)
val enqPtr = enqPtrExt(0).value
val deqPtr = deqPtrExt.value
val sameFlag = enqPtrExt(0).flag === deqPtrExt.flag
......@@ -80,10 +83,8 @@ class LoadQueue extends XSModule with HasDCacheParameters with HasCircularQueueP
*
* Currently, LoadQueue only allows enqueue when #emptyEntries > RenameWidth(EnqWidth)
*/
val validEntries = distanceBetween(enqPtrExt(0), deqPtrExt)
val firedDispatch = io.enq.req.map(_.valid)
io.enq.canAccept := validEntries <= (LoadQueueSize - RenameWidth).U
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(Cat(firedDispatch))}\n")
io.enq.canAccept := allowEnqueue
for (i <- 0 until RenameWidth) {
val offset = if (i == 0) 0.U else PopCount(io.enq.needAlloc.take(i))
val lqIdx = enqPtrExt(offset)
......@@ -100,13 +101,7 @@ class LoadQueue extends XSModule with HasDCacheParameters with HasCircularQueueP
}
io.enq.resp(i) := lqIdx
}
// when io.brqRedirect.valid, we don't allow eneuque even though it may fire.
when (Cat(firedDispatch).orR && io.enq.canAccept && io.enq.sqCanAccept && !io.brqRedirect.valid) {
val enqNumber = PopCount(firedDispatch)
enqPtrExt := VecInit(enqPtrExt.map(_ + enqNumber))
XSInfo("dispatched %d insts to lq\n", enqNumber)
}
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(Cat(io.enq.req.map(_.valid)))}\n")
/**
* Writeback load from load units
......@@ -335,7 +330,6 @@ class LoadQueue extends XSModule with HasDCacheParameters with HasCircularQueueP
XSDebug("load commit %d: idx %d %x\n", i.U, mcommitIdx(i), uop(mcommitIdx(i)).cf.pc)
}
})
deqPtrExt := deqPtrExt + PopCount(loadCommit)
def getFirstOne(mask: Vec[Bool], startMask: UInt) = {
val length = mask.length
......@@ -549,13 +543,38 @@ class LoadQueue extends XSModule with HasDCacheParameters with HasCircularQueueP
allocated(i) := false.B
}
}
// we recover the pointers in the next cycle after redirect
val needCancelReg = RegNext(needCancel)
/**
* update pointers
*/
val lastCycleCancelCount = PopCount(RegNext(needCancel))
// when io.brqRedirect.valid, we don't allow eneuque even though it may fire.
val enqNumber = Mux(io.enq.canAccept && io.enq.sqCanAccept && !io.brqRedirect.valid, PopCount(io.enq.req.map(_.valid)), 0.U)
when (lastCycleRedirect.valid) {
val cancelCount = PopCount(needCancelReg)
enqPtrExt := VecInit(enqPtrExt.map(_ - cancelCount))
// we recover the pointers in the next cycle after redirect
enqPtrExt := VecInit(enqPtrExt.map(_ - lastCycleCancelCount))
}.otherwise {
enqPtrExt := VecInit(enqPtrExt.map(_ + enqNumber))
}
val commitCount = PopCount(loadCommit)
deqPtrExt := deqPtrExt + commitCount
val lastLastCycleRedirect = RegNext(lastCycleRedirect.valid)
val trueValidCounter = distanceBetween(enqPtrExt(0), deqPtrExt)
validCounter := Mux(lastLastCycleRedirect,
trueValidCounter,
validCounter + enqNumber - commitCount
)
allowEnqueue := Mux(io.brqRedirect.valid,
false.B,
Mux(lastLastCycleRedirect,
trueValidCounter <= (LoadQueueSize - RenameWidth).U,
validCounter + enqNumber <= (LoadQueueSize - RenameWidth).U
)
)
// debug info
XSDebug("enqPtrExt %d:%d deqPtrExt %d:%d\n", enqPtrExt(0).flag, enqPtr, deqPtrExt.flag, deqPtr)
......
......@@ -58,6 +58,9 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
require(StoreQueueSize > RenameWidth)
val enqPtrExt = RegInit(VecInit((0 until RenameWidth).map(_.U.asTypeOf(new SqPtr))))
val deqPtrExt = RegInit(VecInit((0 until StorePipelineWidth).map(_.U.asTypeOf(new SqPtr))))
val validCounter = RegInit(0.U(log2Ceil(LoadQueueSize + 1).W))
val allowEnqueue = RegInit(true.B)
val enqPtr = enqPtrExt(0).value
val deqPtr = deqPtrExt(0).value
......@@ -69,10 +72,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
*
* Currently, StoreQueue only allows enqueue when #emptyEntries > RenameWidth(EnqWidth)
*/
val validEntries = distanceBetween(enqPtrExt(0), deqPtrExt(0))
val firedDispatch = io.enq.req.map(_.valid)
io.enq.canAccept := validEntries <= (StoreQueueSize - RenameWidth).U
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(Cat(firedDispatch))}\n")
io.enq.canAccept := allowEnqueue
for (i <- 0 until RenameWidth) {
val offset = if (i == 0) 0.U else PopCount(io.enq.needAlloc.take(i))
val sqIdx = enqPtrExt(offset)
......@@ -87,12 +87,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
}
io.enq.resp(i) := sqIdx
}
when (Cat(firedDispatch).orR && io.enq.canAccept && io.enq.lqCanAccept && !io.brqRedirect.valid) {
val enqNumber = PopCount(firedDispatch)
enqPtrExt := VecInit(enqPtrExt.map(_ + enqNumber))
XSInfo("dispatched %d insts to sq\n", enqNumber)
}
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(Cat(io.enq.req.map(_.valid)))}\n")
/**
* Writeback store from store units
......@@ -104,7 +99,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
* instead of pending to avoid sending them to lower level.
* (2) For an mmio instruction without exceptions, we mark it as pending.
* When the instruction reaches ROB's head, StoreQueue sends it to uncache channel.
* Upon receiving the response, StoreQueue writes back the instruction
* Upon receiving the response, StoreQueue writes back the instruction
* through arbiter with store units. It will later commit as normal.
*/
for (i <- 0 until StorePipelineWidth) {
......@@ -246,7 +241,7 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
when (io.mmioStout.fire()) {
writebacked(deqPtr) := true.B
allocated(deqPtr) := false.B
deqPtrExt := VecInit(deqPtrExt.map(_ + 1.U))
}
/**
......@@ -284,14 +279,10 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
XSDebug("sbuffer "+i+" fire: ptr %d\n", ptr)
}
}
// note that sbuffer will not accept req(1) if req(0) is not accepted.
when (Cat(io.sbuffer.map(_.fire())).orR) {
val stepForward = Mux(io.sbuffer(1).fire(), 2.U, 1.U)
deqPtrExt := VecInit(deqPtrExt.map(_ + stepForward))
when (io.sbuffer(1).fire()) {
assert(io.sbuffer(0).fire())
}
when (io.sbuffer(1).fire()) {
assert(io.sbuffer(0).fire())
}
if (!env.FPGAPlatform) {
val storeCommit = PopCount(io.sbuffer.map(_.fire()))
val waddr = VecInit(io.sbuffer.map(req => SignExt(req.bits.addr, 64)))
......@@ -316,13 +307,45 @@ class StoreQueue extends XSModule with HasDCacheParameters with HasCircularQueue
allocated(i) := false.B
}
}
// we recover the pointers in the next cycle after redirect
val lastCycleRedirectValid = RegNext(io.brqRedirect.valid)
val needCancelCount = PopCount(RegNext(needCancel))
when (lastCycleRedirectValid) {
enqPtrExt := VecInit(enqPtrExt.map(_ - needCancelCount))
/**
* update pointers
*/
val lastCycleRedirect = RegNext(io.brqRedirect.valid)
val lastCycleCancelCount = PopCount(RegNext(needCancel))
// when io.brqRedirect.valid, we don't allow eneuque even though it may fire.
val enqNumber = Mux(io.enq.canAccept && io.enq.lqCanAccept && !io.brqRedirect.valid, PopCount(io.enq.req.map(_.valid)), 0.U)
when (lastCycleRedirect) {
// we recover the pointers in the next cycle after redirect
enqPtrExt := VecInit(enqPtrExt.map(_ - lastCycleCancelCount))
}.otherwise {
enqPtrExt := VecInit(enqPtrExt.map(_ + enqNumber))
}
deqPtrExt := Mux(io.sbuffer(1).fire(),
VecInit(deqPtrExt.map(_ + 2.U)),
Mux(io.sbuffer(0).fire() || io.mmioStout.fire(),
VecInit(deqPtrExt.map(_ + 1.U)),
deqPtrExt
)
)
val lastLastCycleRedirect = RegNext(lastCycleRedirect)
val dequeueCount = Mux(io.sbuffer(1).fire(), 2.U, Mux(io.sbuffer(0).fire() || io.mmioStout.fire(), 1.U, 0.U))
val trueValidCounter = distanceBetween(enqPtrExt(0), deqPtrExt(0))
validCounter := Mux(lastLastCycleRedirect,
trueValidCounter - dequeueCount,
validCounter + enqNumber - dequeueCount
)
allowEnqueue := Mux(io.brqRedirect.valid,
false.B,
Mux(lastLastCycleRedirect,
trueValidCounter <= (StoreQueueSize - RenameWidth).U,
validCounter + enqNumber <= (StoreQueueSize - RenameWidth).U
)
)
// debug info
XSDebug("enqPtrExt %d:%d deqPtrExt %d:%d\n", enqPtrExt(0).flag, enqPtr, deqPtrExt(0).flag, deqPtr)
......
......@@ -93,6 +93,7 @@ package object xiangshan {
def apply() = UInt(2.W)
def isLoadStore(commitType: UInt) = commitType(1)
def lsInstIsStore(commitType: UInt) = commitType(0)
def isStore(commitType: UInt) = isLoadStore(commitType) && lsInstIsStore(commitType)
def isBranch(commitType: UInt) = commitType(0) && !commitType(1)
}
......
......@@ -2,6 +2,8 @@
#include "sdcard.h"
#include "difftest.h"
#include <getopt.h>
#include<signal.h>
#include<unistd.h>
#include "ram.h"
#include "zlib.h"
#include "compress.h"
......@@ -244,6 +246,16 @@ inline void Emulator::single_cycle() {
cycles ++;
}
#if VM_COVERAGE == 1
uint64_t *max_cycle_ptr = NULL;
// when interrupted, we set max_cycle to zero
// so that the emulator will stop gracefully
void sig_handler(int signo) {
if (signo == SIGINT)
*max_cycle_ptr = 0;
}
#endif
uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
extern void poll_event(void);
extern uint32_t uptime(void);
......@@ -268,6 +280,9 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
// since we are not sure when an emu will stop
// we distinguish multiple dat files by emu start time
time_t start_time = time(NULL);
max_cycle_ptr = &max_cycle;
if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
#endif
while (!Verilated::gotFinish() && trapCode == STATE_RUNNING) {
......@@ -407,6 +422,7 @@ inline char* Emulator::waveform_filename(time_t t) {
static char buf[1024];
char *p = timestamp_filename(t, buf);
strcpy(p, ".vcd");
printf("dump wave to %s...\n", buf);
return buf;
}
......
......@@ -5,6 +5,7 @@ import chisel3._
import chisel3.util._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.{VerilatorBackendAnnotation, LineCoverageAnnotation, ToggleCoverageAnnotation, UserCoverageAnnotation, StructuralCoverageAnnotation}
import chiseltest.legacy.backends.verilator.VerilatorFlags
import chiseltest._
import chisel3.experimental.BundleLiterals._
import firrtl.stage.RunFirrtlTransformAnnotation
......@@ -262,6 +263,7 @@ class L2CacheTest extends AnyFlatSpec with ChiselScalatestTester with Matchers{
ToggleCoverageAnnotation,
UserCoverageAnnotation,
StructuralCoverageAnnotation,
VerilatorFlags(Seq("--output-split 5000", "--output-split-cfuncs 5000")),
RunFirrtlTransformAnnotation(new PrintModuleName)
)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册