X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fexperiment%2Fdcache.py;h=910149e50a5dcc73955592d37dc97f8ec4a58690;hb=4a1ce4a397809a935d4ac79d02115a8d973dfec1;hp=7223ef3f3168a4f062d24d53778bd00307c78453;hpb=aaaf9246fdd8057ce168d2a0f4f00f46861d4dfc;p=soc.git diff --git a/src/soc/experiment/dcache.py b/src/soc/experiment/dcache.py index 7223ef3f..910149e5 100644 --- a/src/soc/experiment/dcache.py +++ b/src/soc/experiment/dcache.py @@ -1,3 +1,17 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020,2021 Luke Kenneth Casson Leighton +# Copyright (C) 2020 Cole Poirier +# Copyright (C) 2020,2021 Cesar Strauss +# Copyright (C) 2021 Tobias Platen +# +# Original dcache.vhdl Copyright of its authors and licensed +# by IBM under CC-BY 4.0 +# https://github.com/antonblanchard/microwatt +# +# Conversion to nmigen funded by NLnet and NGI POINTER under EU Grants +# 871528 and 957073, under the LGPL-v3+ License + """DCache based on Anton Blanchard microwatt dcache.vhdl @@ -13,6 +27,8 @@ Links: * https://libre-soc.org/3d_gpu/architecture/set_associative_cache.jpg * https://bugs.libre-soc.org/show_bug.cgi?id=469 +* https://libre-soc.org/irclog-microwatt/%23microwatt.2021-12-07.log.html + (discussion about brams for ECP5) """ @@ -25,8 +41,9 @@ sys.setrecursionlimit(1000000) from enum import Enum, unique from nmigen import (Module, Signal, Elaboratable, Cat, Repl, Array, Const, - Record) + Record, Memory) from nmutil.util import Display +from nmigen.lib.coding import Decoder from copy import deepcopy from random import randint, seed @@ -48,8 +65,8 @@ from soc.experiment.wb_types import (WB_ADDR_BITS, WB_DATA_BITS, WB_SEL_BITS, WBIOMasterOut, WBIOSlaveOut) from soc.experiment.cache_ram import CacheRam -#from soc.experiment.plru import PLRU -from nmutil.plru import PLRU +from soc.experiment.plru import PLRU, PLRUs +#from nmutil.plru import PLRU, PLRUs # for test from soc.bus.sram import SRAM @@ -62,223 +79,248 @@ from nmutil.sim_tmp_alternative import Simulator from nmutil.util import wrap - -# TODO: make these parameters of DCache at some point -LINE_SIZE = 64 # Line size in bytes -NUM_LINES = 16 # Number of lines in a set -NUM_WAYS = 4 # Number of ways -TLB_SET_SIZE = 64 # L1 DTLB entries per set -TLB_NUM_WAYS = 2 # L1 DTLB number of sets -TLB_LG_PGSZ = 12 # L1 DTLB log_2(page_size) LOG_LENGTH = 0 # Non-zero to enable log data collection -# BRAM organisation: We never access more than -# -- WB_DATA_BITS at a time so to save -# -- resources we make the array only that wide, and -# -- use consecutive indices to make a cache "line" -# -- -# -- ROW_SIZE is the width in bytes of the BRAM -# -- (based on WB, so 64-bits) -ROW_SIZE = WB_DATA_BITS // 8; - -# ROW_PER_LINE is the number of row (wishbone -# transactions) in a line -ROW_PER_LINE = LINE_SIZE // ROW_SIZE - -# BRAM_ROWS is the number of rows in BRAM needed -# to represent the full dcache -BRAM_ROWS = NUM_LINES * ROW_PER_LINE - -print ("ROW_SIZE", ROW_SIZE) -print ("ROW_PER_LINE", ROW_PER_LINE) -print ("BRAM_ROWS", BRAM_ROWS) -print ("NUM_WAYS", NUM_WAYS) - -# Bit fields counts in the address - -# REAL_ADDR_BITS is the number of real address -# bits that we store -REAL_ADDR_BITS = 56 - -# ROW_BITS is the number of bits to select a row -ROW_BITS = log2_int(BRAM_ROWS) - -# ROW_LINE_BITS is the number of bits to select -# a row within a line -ROW_LINE_BITS = log2_int(ROW_PER_LINE) - -# LINE_OFF_BITS is the number of bits for -# the offset in a cache line -LINE_OFF_BITS = log2_int(LINE_SIZE) - -# ROW_OFF_BITS is the number of bits for -# the offset in a row -ROW_OFF_BITS = log2_int(ROW_SIZE) - -# INDEX_BITS is the number if bits to -# select a cache line -INDEX_BITS = log2_int(NUM_LINES) - -# SET_SIZE_BITS is the log base 2 of the set size -SET_SIZE_BITS = LINE_OFF_BITS + INDEX_BITS - -# TAG_BITS is the number of bits of -# the tag part of the address -TAG_BITS = REAL_ADDR_BITS - SET_SIZE_BITS - -# TAG_WIDTH is the width in bits of each way of the tag RAM -TAG_WIDTH = TAG_BITS + 7 - ((TAG_BITS + 7) % 8) - -# WAY_BITS is the number of bits to select a way -WAY_BITS = log2_int(NUM_WAYS) - -# Example of layout for 32 lines of 64 bytes: -layout = """\ - .. tag |index| line | - .. | row | | - .. | |---| | ROW_LINE_BITS (3) - .. | |--- - --| LINE_OFF_BITS (6) - .. | |- --| ROW_OFF_BITS (3) - .. |----- ---| | ROW_BITS (8) - .. |-----| | INDEX_BITS (5) - .. --------| | TAG_BITS (45) -""" -print (layout) -print ("Dcache TAG %d IDX %d ROW_BITS %d ROFF %d LOFF %d RLB %d" % \ - (TAG_BITS, INDEX_BITS, ROW_BITS, - ROW_OFF_BITS, LINE_OFF_BITS, ROW_LINE_BITS)) -print ("index @: %d-%d" % (LINE_OFF_BITS, SET_SIZE_BITS)) -print ("row @: %d-%d" % (LINE_OFF_BITS, ROW_OFF_BITS)) -print ("tag @: %d-%d width %d" % (SET_SIZE_BITS, REAL_ADDR_BITS, TAG_WIDTH)) - -TAG_RAM_WIDTH = TAG_WIDTH * NUM_WAYS - -print ("TAG_RAM_WIDTH", TAG_RAM_WIDTH) - -def CacheTagArray(): - tag_layout = [('valid', 1), - ('tag', TAG_RAM_WIDTH), - ] - return Array(Record(tag_layout, name="tag%d" % x) for x in range(NUM_LINES)) - -def RowPerLineValidArray(): - return Array(Signal(name="rows_valid%d" % x) \ - for x in range(ROW_PER_LINE)) - -# L1 TLB -TLB_SET_BITS = log2_int(TLB_SET_SIZE) -TLB_WAY_BITS = log2_int(TLB_NUM_WAYS) -TLB_EA_TAG_BITS = 64 - (TLB_LG_PGSZ + TLB_SET_BITS) -TLB_TAG_WAY_BITS = TLB_NUM_WAYS * TLB_EA_TAG_BITS -TLB_PTE_BITS = 64 -TLB_PTE_WAY_BITS = TLB_NUM_WAYS * TLB_PTE_BITS; - def ispow2(x): return (1< '0') & r1.reload_tag; - """ - comb += ct.word_select(i, TAG_WIDTH).eq(r1.reload_tag) - sync += cache_tags[r1.store_index].tag.eq(ct) + replace_way_onehot = Signal(self.NUM_WAYS) + comb += replace_way_onehot.eq(1<