diff --git a/tools/backend/lsq-generator-python/core_gen/configs.py b/tools/backend/lsq-generator-python/core_gen/configs.py index 3e63b10f3..7d9cf0c39 100644 --- a/tools/backend/lsq-generator-python/core_gen/configs.py +++ b/tools/backend/lsq-generator-python/core_gen/configs.py @@ -93,16 +93,10 @@ def __init__(self, config: dict) -> None: self.ldqAddrW = math.ceil(math.log2(self.numLdqEntries)) self.stqAddrW = math.ceil(math.log2(self.numStqEntries)) - # Original empty assignment assumes the size of load or store queue to be always a multiple of 2 - if (self.numLdqEntries & (self.numLdqEntries % 2 == 0)): - self.emptyLdAddrW = math.ceil(math.log2(self.numLdqEntries+1)) - else: - self.emptyLdAddrW = math.ceil(math.log2(self.numLdqEntries)) + 1 - - if (self.numStqEntries & (self.numStqEntries % 2 == 0)): - self.emptyStAddrW = math.ceil(math.log2(self.numStqEntries+1)) - else: - self.emptyStAddrW = math.ceil(math.log2(self.numStqEntries)) + 1 + # Use one more bit to be able to represent the empty state of the queue when the number of entries is a power of 2 + self.emptyLdAddrW = self.ldqAddrW + 1 + self.emptyStAddrW = self.stqAddrW + 1 + # Check the number of ports, if num*Ports == 0, set it to 1 self.ldpAddrW = math.ceil(math.log2(self.numLdPorts if self.numLdPorts > 0 else 1)) self.stpAddrW = math.ceil(math.log2(self.numStPorts if self.numStPorts > 0 else 1)) @@ -120,3 +114,8 @@ def __init__(self, config: dict) -> None: assert (len(self.gaLdOrder) == self.numGroups) assert (len(self.gaLdPortIdx) == self.numGroups) assert (len(self.gaStPortIdx) == self.numGroups) + + # An LSQ with N load/store entries can only support up to N-1 loads/stores per group. + for i in range(self.numGroups): + assert self.gaNumLoads[i] < self.numLdqEntries, f"group {i}: too many loads ({self.gaNumLoads[i]}) for load queue with {self.numLdqEntries} entries!" + assert self.gaNumStores[i] < self.numStqEntries, f"group {i}: too many stores ({self.gaNumStores[i]}) for store queue with {self.numStqEntries} entries!" diff --git a/tools/backend/lsq-generator-python/core_gen/generators/lsq.py b/tools/backend/lsq-generator-python/core_gen/generators/lsq.py index d71de92eb..5086b4e3b 100644 --- a/tools/backend/lsq-generator-python/core_gen/generators/lsq.py +++ b/tools/backend/lsq-generator-python/core_gen/generators/lsq.py @@ -599,6 +599,8 @@ def generate(self, lsq_submodules, path_rtl) -> None: if self.configs.pipe0: can_bypass_p0.regInit(init=[0]*self.configs.numLdqEntries) + ldq_head_oh_pcomp = LogicVec( + ctx, 'ldq_head_oh_pcomp', pipe_comp_type, self.configs.numLdqEntries) ldq_alloc_pcomp = LogicArray( ctx, 'ldq_alloc_pcomp', pipe_comp_type, self.configs.numLdqEntries) ldq_addr_valid_pcomp = LogicArray( @@ -626,6 +628,7 @@ def generate(self, lsq_submodules, path_rtl) -> None: store_completed = LogicArray(ctx, 'store_completed', 'w', self.configs.numStqEntries) if self.configs.pipeComp: + ldq_head_oh_pcomp.regInit(init=0) ldq_alloc_pcomp.regInit(init=[0]*self.configs.numLdqEntries) ldq_addr_valid_pcomp.regInit() stq_alloc_pcomp.regInit(init=[0]*self.configs.numStqEntries) @@ -635,6 +638,7 @@ def generate(self, lsq_submodules, path_rtl) -> None: addr_same_pcomp.regInit() store_is_older_pcomp.regInit() + arch += Op(ctx, ldq_head_oh_pcomp, ldq_head_oh) for i in range(0, self.configs.numLdqEntries): arch += Op(ctx, (ldq_alloc_pcomp, i), (ldq_alloc, i)) arch += Op(ctx, (ldq_addr_valid_pcomp, i), @@ -747,7 +751,7 @@ def generate(self, lsq_submodules, path_rtl) -> None: ctx, 'ldq_head_oh_p0', pipe0_type, self.configs.numLdqEntries) if self.configs.pipe0: ldq_head_oh_p0.regInit() - arch += Op(ctx, ldq_head_oh_p0, ldq_head_oh) + arch += Op(ctx, ldq_head_oh_p0, ldq_head_oh_pcomp) can_load_list = [] can_load_list.append(can_load) diff --git a/tools/backend/lsq-generator-python/core_gen/utils.py b/tools/backend/lsq-generator-python/core_gen/utils.py index d75c2f6c2..cc94af9cf 100644 --- a/tools/backend/lsq-generator-python/core_gen/utils.py +++ b/tools/backend/lsq-generator-python/core_gen/utils.py @@ -420,22 +420,19 @@ def MaskLess(din, size) -> str: def IntToBits(din, size=None) -> str: if size == None: - if din: + if din == 1: return "'1'" - else: + elif din == 0: return "'0'" + else: + raise ValueError("IntToBits: Invalid value for size=None! Cannot represent the value as a single bit!") else: - str_ret = '"' - for i in range(0, size): - if din % 2 == 0: - str_ret = "0" + str_ret - else: - str_ret = "1" + str_ret - din = din // 2 - str_ret = '"' + str_ret - if din != 0: - raise ValueError("Unknown value!") - return str_ret + if din < 0: + raise ValueError("IntToBits: Negative value cannot be converted to bits!") + if din >= (1 << size): + raise ValueError(f"IntToBits: Value {din} cannot be represented with {size} bit(s)!") + bits = f"{din:0{size}b}" + return f'"{bits}"' def Zero(size) -> str: