diff --git a/CMakeLists.txt b/CMakeLists.txt index c1be0376..0cdf6184 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ endif() set(DRAMSYS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") set(DRAMSYS_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib") set(DRAMSYS_TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests") -set(DRAMSYS_RESOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources") +set(DRAMSYS_RESOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configs") set(DRAMSYS_EXTENSIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extensions") ### Build options ### @@ -137,6 +137,7 @@ FetchContent_Declare( GIT_REPOSITORY https://github.com/accellera-official/systemc.git GIT_TAG 2.3.4) +set(DISABLE_COPYRIGHT_MESSAGE True) FetchContent_MakeAvailable(systemc) set_target_properties(systemc PROPERTIES FOLDER lib) diff --git a/configs/README.md b/configs/README.md index 6ed1fbef..fdda34af 100644 --- a/configs/README.md +++ b/configs/README.md @@ -19,7 +19,6 @@ The JSON code below shows an example configuration: }, { "clkMhz": 2000, - "type": "generator", "name": "gen0", "numRequests": 2000, "rwRatio": 0.85, @@ -32,7 +31,6 @@ The JSON code below shows an example configuration: }, { "clkMhz": 1000, - "type": "hammer", "name": "ham0", "numRequests": 4000, "rowIncrement": 2097152 @@ -49,11 +47,58 @@ Field Descriptions: - "mcconfig": memory controller configuration file - "tracesetup": The trace setup is only used in standalone mode. In library mode or gem5 mode the trace setup is ignored. Each device should be added as a json object inside the "tracesetup" array. -Each **trace setup** device configuration can be a **trace player** ("type": "player"), a **traffic generator** ("type": "generator") or a **row hammer generator** ("type": "hammer"). By not specifing the **type** parameter, the device will act as a **trace player**. +Each **trace setup** device configuration can be a **trace player**, a **traffic generator** or a **row hammer generator**. The type will be automatically concluded based on the given parameters. All device configurations must define a **clkMhz** (operation frequency of the **traffic initiator**) and a **name** (in case of a trace player this specifies the **trace file** to play; in case of a generator this field is only for identification purposes). The **maxPendingReadRequests** and **maxPendingWriteRequests** parameters define the maximum number of outstanding read/write requests. The current implementation delays all memory accesses if one limit is reached. The default value (0) disables the limit. -A **traffic generator** can be configured to generate **numRequests** requests in total, of which the **rwRatio** field defines the probability of one request being a read request. The length of a request (in bytes) can be specified with the **dataLength** parameter. The **seed** parameter can be used to produce identical results for all simulations. **minAddress** and **maxAddress** specify the address range, by default the whole address range is used. The parameter **addressDistribution** can either be set to **random** or **sequential**. In case of **sequential** the additional **addressIncrement** field must be specified, defining the address increment after each request. +A **traffic generator** can be configured to generate **numRequests** requests in total, of which the **rwRatio** field defines the probability of one request being a read request. The length of a request (in bytes) can be specified with the **dataLength** parameter. The **seed** parameter can be used to produce identical results for all simulations. **minAddress** and **maxAddress** specify the address range, by default the whole address range is used. The parameter **addressDistribution** can either be set to **random** or **sequential**. In case of **sequential** the additional **addressIncrement** field must be specified, defining the address increment after each request. The address alignment of the random generator can be configured using the **dataAlignment** field. By default, the addresses will be naturally aligned at dataLength. + +For more advanced use cases, the traffic generator is capable of acting as a state machine with multiple states that can be configured in the same manner as described earlier. Each state is specified as an element in the **states** array. Each state has to include an unique **id**. The **transitions** field describes all possible transitions from one state to another with their associated **probability**. +In the context of a state machine, there exists another type of generator: the idle generator. In an idle state no requests are issued. The parameter **idleClks** specifies the duration of the idle state. + +An example of a state machine configuration with 3 states is shown below. + +```json +{ + "clkMhz": 100, + "maxPendingReadRequests": 8, + "name": "StateMachine", + "states": [ + { + "addressDistribution": "sequential", + "addressIncrement": 256, + "id": 0, + "maxAddress": 1024, + "numRequests": 1000, + "rwRatio": 0.5 + }, + { + "id": 1, + "idleClks": 1000 + }, + { + "addressDistribution": "random", + "id": 2, + "maxAddress": 2048, + "minAddress": 1024, + "numRequests": 1000, + "rwRatio": 0.75 + } + ], + "transitions": [ + { + "from": 0, + "probability": 1.0, + "to": 1 + }, + { + "from": 1, + "probability": 1.0, + "to": 2 + } + ] +} +``` The **row hammer generator** is a special traffic generator that mimics a row hammer attack. It generates **numRequests** alternating read requests to two different addresses. The first address is 0x0, the second address is specified by the **rowIncrement** parameter and should decode to a different row in the same bank. Since only one outstanding request is allowed, the controller cannot perform any reordering, forcing a row switch (precharge and activate) for each access. That way the number of activations on the target rows are maximized. @@ -182,7 +227,7 @@ Used fields: ```json { - "CONGEN": { + "addressmapping": { "XOR": [ { "FIRST": 13, diff --git a/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_brc.json b/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_brc.json index 3999c105..5438a40d 100644 --- a/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_brc.json +++ b/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 28, 29, diff --git a/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.json b/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.json index d1bcfe70..91c90fa6 100644 --- a/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.json +++ b/configs/addressmapping/am_ddr3_4x4Gbx16_dimm_p2KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 13, 14, diff --git a/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_brc.json b/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_brc.json index 13ee107d..fca7cfed 100644 --- a/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_brc.json +++ b/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 27, 28, diff --git a/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.json b/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.json index 81ac8ef6..3a4a8044 100644 --- a/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_ddr3_8x1Gbx8_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 13, 14, diff --git a/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_brc.json b/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_brc.json index 3999c105..5438a40d 100644 --- a/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_brc.json +++ b/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 28, 29, diff --git a/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.json b/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.json index d1bcfe70..91c90fa6 100644 --- a/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_ddr3_8x2Gbx8_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 13, 14, diff --git a/configs/addressmapping/am_ddr3_x16_brc.json b/configs/addressmapping/am_ddr3_x16_brc.json index dbd6a2d2..73d2c68e 100644 --- a/configs/addressmapping/am_ddr3_x16_brc.json +++ b/configs/addressmapping/am_ddr3_x16_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 26, 27, diff --git a/configs/addressmapping/am_ddr3_x16_rbc.json b/configs/addressmapping/am_ddr3_x16_rbc.json index e7cbcd22..3d841bde 100644 --- a/configs/addressmapping/am_ddr3_x16_rbc.json +++ b/configs/addressmapping/am_ddr3_x16_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 13, 14, diff --git a/configs/addressmapping/am_ddr4_8x4Gbx8_dimm_p1KB_brc.json b/configs/addressmapping/am_ddr4_8x4Gbx8_dimm_p1KB_brc.json index 7b9f8340..689baddf 100644 --- a/configs/addressmapping/am_ddr4_8x4Gbx8_dimm_p1KB_brc.json +++ b/configs/addressmapping/am_ddr4_8x4Gbx8_dimm_p1KB_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANKGROUP_BIT":[ 28, 29 diff --git a/configs/addressmapping/am_ddr5_2x2x8x4Gbx4_dimm_p1KB_rbc.json b/configs/addressmapping/am_ddr5_2x2x8x4Gbx4_dimm_p1KB_rbc.json index 5e42017b..0652961c 100644 --- a/configs/addressmapping/am_ddr5_2x2x8x4Gbx4_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_ddr5_2x2x8x4Gbx4_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0, 1 diff --git a/configs/addressmapping/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json b/configs/addressmapping/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json index 7e02f877..3f6970d8 100644 --- a/configs/addressmapping/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_ddr5_2x4x1Gbx8_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0, 1 diff --git a/configs/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json b/configs/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json index bce5038e..143f714a 100644 --- a/configs/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0, 1 diff --git a/configs/addressmapping/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json b/configs/addressmapping/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json index 48f1301d..e45fd809 100644 --- a/configs/addressmapping/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_ddr5_2x8x8x2Gbx4_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0, 1 diff --git a/configs/addressmapping/am_hbm2_8Gb_pc_brc.json b/configs/addressmapping/am_hbm2_8Gb_pc_brc.json index 687e35d7..87879fdc 100644 --- a/configs/addressmapping/am_hbm2_8Gb_pc_brc.json +++ b/configs/addressmapping/am_hbm2_8Gb_pc_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "PSEUDOCHANNEL_BIT":[ 29 ], diff --git a/configs/addressmapping/am_hbm3_8Gb_pc_brc.json b/configs/addressmapping/am_hbm3_8Gb_pc_brc.json index 7b7c076f..31812705 100644 --- a/configs/addressmapping/am_hbm3_8Gb_pc_brc.json +++ b/configs/addressmapping/am_hbm3_8Gb_pc_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "PSEUDOCHANNEL_BIT":[ 28 ], diff --git a/configs/addressmapping/am_lpddr4_1Gbx16_baroco.json b/configs/addressmapping/am_lpddr4_1Gbx16_baroco.json index bf827c06..03dc8bd7 100644 --- a/configs/addressmapping/am_lpddr4_1Gbx16_baroco.json +++ b/configs/addressmapping/am_lpddr4_1Gbx16_baroco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 28, 29, diff --git a/configs/addressmapping/am_lpddr4_1Gbx16_robaco.json b/configs/addressmapping/am_lpddr4_1Gbx16_robaco.json index 9e86d16e..69a9c9b5 100644 --- a/configs/addressmapping/am_lpddr4_1Gbx16_robaco.json +++ b/configs/addressmapping/am_lpddr4_1Gbx16_robaco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 11, 12, diff --git a/configs/addressmapping/am_lpddr4_1Gbx16_rocoba.json b/configs/addressmapping/am_lpddr4_1Gbx16_rocoba.json index f4091b45..eafa99fe 100644 --- a/configs/addressmapping/am_lpddr4_1Gbx16_rocoba.json +++ b/configs/addressmapping/am_lpddr4_1Gbx16_rocoba.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 5, 6, diff --git a/configs/addressmapping/am_lpddr4_512Mbx16_baroco.json b/configs/addressmapping/am_lpddr4_512Mbx16_baroco.json index e9b3ac9f..8e9948b2 100644 --- a/configs/addressmapping/am_lpddr4_512Mbx16_baroco.json +++ b/configs/addressmapping/am_lpddr4_512Mbx16_baroco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 27, 28, diff --git a/configs/addressmapping/am_lpddr4_512Mbx16_robaco.json b/configs/addressmapping/am_lpddr4_512Mbx16_robaco.json index f4c2c3dd..baa9dcd2 100644 --- a/configs/addressmapping/am_lpddr4_512Mbx16_robaco.json +++ b/configs/addressmapping/am_lpddr4_512Mbx16_robaco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 11, 12, diff --git a/configs/addressmapping/am_lpddr4_512Mbx16_rocoba.json b/configs/addressmapping/am_lpddr4_512Mbx16_rocoba.json index a8142937..455ae3a3 100644 --- a/configs/addressmapping/am_lpddr4_512Mbx16_rocoba.json +++ b/configs/addressmapping/am_lpddr4_512Mbx16_rocoba.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 5, 6, diff --git a/configs/addressmapping/am_lpddr4_8Gbx16_brc.json b/configs/addressmapping/am_lpddr4_8Gbx16_brc.json index e9b3ac9f..8e9948b2 100644 --- a/configs/addressmapping/am_lpddr4_8Gbx16_brc.json +++ b/configs/addressmapping/am_lpddr4_8Gbx16_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 27, 28, diff --git a/configs/addressmapping/am_lpddr5_1Gbx16_16B_robaco.json b/configs/addressmapping/am_lpddr5_1Gbx16_16B_robaco.json index a48e5b4f..2c2b96b8 100644 --- a/configs/addressmapping/am_lpddr5_1Gbx16_16B_robaco.json +++ b/configs/addressmapping/am_lpddr5_1Gbx16_16B_robaco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_1Gbx16_16B_rocoba.json b/configs/addressmapping/am_lpddr5_1Gbx16_16B_rocoba.json index 52fde69a..8d78bf4a 100644 --- a/configs/addressmapping/am_lpddr5_1Gbx16_16B_rocoba.json +++ b/configs/addressmapping/am_lpddr5_1Gbx16_16B_rocoba.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_1Gbx16_8B_robaco.json b/configs/addressmapping/am_lpddr5_1Gbx16_8B_robaco.json index a131562a..82b756fc 100644 --- a/configs/addressmapping/am_lpddr5_1Gbx16_8B_robaco.json +++ b/configs/addressmapping/am_lpddr5_1Gbx16_8B_robaco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_1Gbx16_8B_rocoba.json b/configs/addressmapping/am_lpddr5_1Gbx16_8B_rocoba.json index aaf6a029..1f5d2cfe 100644 --- a/configs/addressmapping/am_lpddr5_1Gbx16_8B_rocoba.json +++ b/configs/addressmapping/am_lpddr5_1Gbx16_8B_rocoba.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_1Gbx16_BG_robacobg.json b/configs/addressmapping/am_lpddr5_1Gbx16_BG_robacobg.json index 0fd3b6c0..bf80d312 100644 --- a/configs/addressmapping/am_lpddr5_1Gbx16_BG_robacobg.json +++ b/configs/addressmapping/am_lpddr5_1Gbx16_BG_robacobg.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_1Gbx16_BG_rocobabg.json b/configs/addressmapping/am_lpddr5_1Gbx16_BG_rocobabg.json index 2552ccd3..88629310 100644 --- a/configs/addressmapping/am_lpddr5_1Gbx16_BG_rocobabg.json +++ b/configs/addressmapping/am_lpddr5_1Gbx16_BG_rocobabg.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_512Mbx16_16B_robaco.json b/configs/addressmapping/am_lpddr5_512Mbx16_16B_robaco.json index 4f5bfd86..8b91cc1e 100644 --- a/configs/addressmapping/am_lpddr5_512Mbx16_16B_robaco.json +++ b/configs/addressmapping/am_lpddr5_512Mbx16_16B_robaco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_512Mbx16_16B_rocoba.json b/configs/addressmapping/am_lpddr5_512Mbx16_16B_rocoba.json index c5cf4d95..8630b987 100644 --- a/configs/addressmapping/am_lpddr5_512Mbx16_16B_rocoba.json +++ b/configs/addressmapping/am_lpddr5_512Mbx16_16B_rocoba.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_512Mbx16_8B_robaco.json b/configs/addressmapping/am_lpddr5_512Mbx16_8B_robaco.json index 1846604c..284f8957 100644 --- a/configs/addressmapping/am_lpddr5_512Mbx16_8B_robaco.json +++ b/configs/addressmapping/am_lpddr5_512Mbx16_8B_robaco.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_512Mbx16_8B_rocoba.json b/configs/addressmapping/am_lpddr5_512Mbx16_8B_rocoba.json index 9c00c8d9..35b67ef4 100644 --- a/configs/addressmapping/am_lpddr5_512Mbx16_8B_rocoba.json +++ b/configs/addressmapping/am_lpddr5_512Mbx16_8B_rocoba.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_512Mbx16_BG_robacobg.json b/configs/addressmapping/am_lpddr5_512Mbx16_BG_robacobg.json index bf283cd6..94066723 100644 --- a/configs/addressmapping/am_lpddr5_512Mbx16_BG_robacobg.json +++ b/configs/addressmapping/am_lpddr5_512Mbx16_BG_robacobg.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_lpddr5_512Mbx16_BG_rocobabg.json b/configs/addressmapping/am_lpddr5_512Mbx16_BG_rocobabg.json index c85e1b7e..3898a373 100644 --- a/configs/addressmapping/am_lpddr5_512Mbx16_BG_rocobabg.json +++ b/configs/addressmapping/am_lpddr5_512Mbx16_BG_rocobabg.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BYTE_BIT": [ 0 ], diff --git a/configs/addressmapping/am_ranktest.json b/configs/addressmapping/am_ranktest.json index 720b214e..accf2165 100644 --- a/configs/addressmapping/am_ranktest.json +++ b/configs/addressmapping/am_ranktest.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "RANK_BIT":[ 30, 31 diff --git a/configs/addressmapping/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json b/configs/addressmapping/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json index d1bcfe70..91c90fa6 100644 --- a/configs/addressmapping/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json +++ b/configs/addressmapping/am_stt-mram_8x2Gbx8_dimm_p1KB_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 13, 14, diff --git a/configs/addressmapping/am_wideio2_4x64_4x2Gb_brc.json b/configs/addressmapping/am_wideio2_4x64_4x2Gb_brc.json index 512b8090..e1267bcc 100644 --- a/configs/addressmapping/am_wideio2_4x64_4x2Gb_brc.json +++ b/configs/addressmapping/am_wideio2_4x64_4x2Gb_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 25, 26, diff --git a/configs/addressmapping/am_wideio2_4x64_4x2Gb_rbc.json b/configs/addressmapping/am_wideio2_4x64_4x2Gb_rbc.json index 58bc5ce4..e90f4110 100644 --- a/configs/addressmapping/am_wideio2_4x64_4x2Gb_rbc.json +++ b/configs/addressmapping/am_wideio2_4x64_4x2Gb_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 12, 13, diff --git a/configs/addressmapping/am_wideio_4x1Gb_brc.json b/configs/addressmapping/am_wideio_4x1Gb_brc.json index 7f51385c..6f05d067 100644 --- a/configs/addressmapping/am_wideio_4x1Gb_brc.json +++ b/configs/addressmapping/am_wideio_4x1Gb_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 25, 26 diff --git a/configs/addressmapping/am_wideio_4x1Gb_rbc.json b/configs/addressmapping/am_wideio_4x1Gb_rbc.json index cbe47587..cf088be1 100644 --- a/configs/addressmapping/am_wideio_4x1Gb_rbc.json +++ b/configs/addressmapping/am_wideio_4x1Gb_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 11, 12 diff --git a/configs/addressmapping/am_wideio_4x256Mb_brc.json b/configs/addressmapping/am_wideio_4x256Mb_brc.json index 52d665e5..3d4ae4d6 100644 --- a/configs/addressmapping/am_wideio_4x256Mb_brc.json +++ b/configs/addressmapping/am_wideio_4x256Mb_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 23, 24 diff --git a/configs/addressmapping/am_wideio_4x256Mb_rbc.json b/configs/addressmapping/am_wideio_4x256Mb_rbc.json index fc5f8b2a..d855313d 100644 --- a/configs/addressmapping/am_wideio_4x256Mb_rbc.json +++ b/configs/addressmapping/am_wideio_4x256Mb_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 11, 12 diff --git a/configs/addressmapping/am_wideio_4x2Gb_brc.json b/configs/addressmapping/am_wideio_4x2Gb_brc.json index 3040e90a..961a4a36 100644 --- a/configs/addressmapping/am_wideio_4x2Gb_brc.json +++ b/configs/addressmapping/am_wideio_4x2Gb_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 26, 27 diff --git a/configs/addressmapping/am_wideio_4x2Gb_rbc.json b/configs/addressmapping/am_wideio_4x2Gb_rbc.json index 76a9de62..15ddf749 100644 --- a/configs/addressmapping/am_wideio_4x2Gb_rbc.json +++ b/configs/addressmapping/am_wideio_4x2Gb_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 11, 12 diff --git a/configs/addressmapping/am_wideio_4x4Gb_brc.json b/configs/addressmapping/am_wideio_4x4Gb_brc.json index 8c16b58c..639ba547 100644 --- a/configs/addressmapping/am_wideio_4x4Gb_brc.json +++ b/configs/addressmapping/am_wideio_4x4Gb_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 27, 28 diff --git a/configs/addressmapping/am_wideio_4x4Gb_rbc.json b/configs/addressmapping/am_wideio_4x4Gb_rbc.json index e8d1b1e8..4fa24317 100644 --- a/configs/addressmapping/am_wideio_4x4Gb_rbc.json +++ b/configs/addressmapping/am_wideio_4x4Gb_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 12, 13 diff --git a/configs/addressmapping/am_wideio_4x512Mb_brc.json b/configs/addressmapping/am_wideio_4x512Mb_brc.json index 18ab6414..c07fcc40 100644 --- a/configs/addressmapping/am_wideio_4x512Mb_brc.json +++ b/configs/addressmapping/am_wideio_4x512Mb_brc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 24, 25 diff --git a/configs/addressmapping/am_wideio_4x512Mb_rbc.json b/configs/addressmapping/am_wideio_4x512Mb_rbc.json index 62578383..60cacb06 100644 --- a/configs/addressmapping/am_wideio_4x512Mb_rbc.json +++ b/configs/addressmapping/am_wideio_4x512Mb_rbc.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 11, 12 diff --git a/configs/addressmapping/am_wideio_thermal.json b/configs/addressmapping/am_wideio_thermal.json index 96be2a29..c8597163 100644 --- a/configs/addressmapping/am_wideio_thermal.json +++ b/configs/addressmapping/am_wideio_thermal.json @@ -1,5 +1,5 @@ { - "CONGEN": { + "addressmapping": { "BANK_BIT": [ 4, 5 diff --git a/configs/memspec/JEDEC_2x2x8x4Gbx4_DDR5-3200A.json b/configs/memspec/JEDEC_2x2x8x4Gbx4_DDR5-3200A.json index a53f77d8..e4bdd037 100644 --- a/configs/memspec/JEDEC_2x2x8x4Gbx4_DDR5-3200A.json +++ b/configs/memspec/JEDEC_2x2x8x4Gbx4_DDR5-3200A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 8, "CCD_L_WR_slr": 32, "CCD_L_WR2_slr": 16, + "CCD_M_slr": 8, + "CCD_M_WR_slr": 32, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 16, + "WTR_M": 16, "WTR_S": 4, "RFC1_slr": 312, "RFC2_slr": 208, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3200A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3200A.json index 4e65f215..f719e72a 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3200A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3200A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 8, "CCD_L_WR_slr": 32, "CCD_L_WR2_slr": 16, + "CCD_M_slr": 8, + "CCD_M_WR_slr": 32, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 16, + "WTR_M": 16, "WTR_S": 4, "RFC1_slr": 312, "RFC2_slr": 208, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3600A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3600A.json index ba477a9b..359b362a 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3600A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-3600A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 9, "CCD_L_WR_slr": 36, "CCD_L_WR2_slr": 18, + "CCD_M_slr": 9, + "CCD_M_WR_slr": 36, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 18, + "WTR_M": 18, "WTR_S": 5, "RFC1_slr": 351, "RFC2_slr": 234, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4000A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4000A.json index ee642481..411f7e07 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4000A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4000A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 10, "CCD_L_WR_slr": 40, "CCD_L_WR2_slr": 20, + "CCD_M_slr": 10, + "CCD_M_WR_slr": 40, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 20, + "WTR_M": 20, "WTR_S": 5, "RFC1_slr": 390, "RFC2_slr": 260, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4400A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4400A.json index 9c20c24e..9f270893 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4400A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4400A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 11, "CCD_L_WR_slr": 44, "CCD_L_WR2_slr": 22, + "CCD_M_slr": 11, + "CCD_M_WR_slr": 44, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 22, + "WTR_M": 22, "WTR_S": 6, "RFC1_slr": 429, "RFC2_slr": 286, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4800A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4800A.json index 3e01074e..b2ee9f4c 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4800A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-4800A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 12, "CCD_L_WR_slr": 48, "CCD_L_WR2_slr": 24, + "CCD_M_slr": 12, + "CCD_M_WR_slr": 48, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 24, + "WTR_M": 24, "WTR_S": 6, "RFC1_slr": 468, "RFC2_slr": 312, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5200A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5200A.json index a0334a70..f6195751 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5200A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5200A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 13, "CCD_L_WR_slr": 52, "CCD_L_WR2_slr": 26, + "CCD_M_slr": 13, + "CCD_M_WR_slr": 52, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 26, + "WTR_M": 26, "WTR_S": 7, "RFC1_slr": 507, "RFC2_slr": 338, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5600A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5600A.json index cbd646be..dac8025d 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5600A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-5600A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 14, "CCD_L_WR_slr": 56, "CCD_L_WR2_slr": 28, + "CCD_M_slr": 14, + "CCD_M_WR_slr": 56, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 28, + "WTR_M": 28, "WTR_S": 7, "RFC1_slr": 546, "RFC2_slr": 364, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6000A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6000A.json index 3cda8802..a916a36b 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6000A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6000A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 15, "CCD_L_WR_slr": 60, "CCD_L_WR2_slr": 30, + "CCD_M_slr": 15, + "CCD_M_WR_slr": 60, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 30, + "WTR_M": 30, "WTR_S": 8, "RFC1_slr": 585, "RFC2_slr": 390, diff --git a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6400A.json b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6400A.json index 66cf4a2e..3cd3e234 100644 --- a/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6400A.json +++ b/configs/memspec/JEDEC_2x4x1Gbx8_DDR5-6400A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 16, "CCD_L_WR_slr": 64, "CCD_L_WR2_slr": 32, + "CCD_M_slr": 16, + "CCD_M_WR_slr": 64, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 32, + "WTR_M": 32, "WTR_S": 8, "RFC1_slr": 624, "RFC2_slr": 416, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json index 9b3e1e4e..8f72eba6 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 8, "CCD_L_WR_slr": 32, "CCD_L_WR2_slr": 16, + "CCD_M_slr": 8, + "CCD_M_WR_slr": 32, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 16, + "WTR_M": 16, "WTR_S": 4, "RFC1_slr": 312, "RFC2_slr": 208, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3600A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3600A.json index 26a82afa..dd7baaf9 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3600A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-3600A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 9, "CCD_L_WR_slr": 36, "CCD_L_WR2_slr": 18, + "CCD_M_slr": 9, + "CCD_M_WR_slr": 36, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 18, + "WTR_M": 18, "WTR_S": 5, "RFC1_slr": 351, "RFC2_slr": 234, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4000A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4000A.json index d518b7e8..c7f182eb 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4000A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4000A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 10, "CCD_L_WR_slr": 40, "CCD_L_WR2_slr": 20, + "CCD_M_slr": 10, + "CCD_M_WR_slr": 40, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 20, + "WTR_M": 20, "WTR_S": 5, "RFC1_slr": 390, "RFC2_slr": 260, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4400A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4400A.json index b7933630..fe7878e2 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4400A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4400A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 11, "CCD_L_WR_slr": 44, "CCD_L_WR2_slr": 22, + "CCD_M_slr": 11, + "CCD_M_WR_slr": 44, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 22, + "WTR_M": 22, "WTR_S": 6, "RFC1_slr": 429, "RFC2_slr": 286, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4800A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4800A.json index 3dc97958..c9b2f126 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4800A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-4800A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 12, "CCD_L_WR_slr": 48, "CCD_L_WR2_slr": 24, + "CCD_M_slr": 12, + "CCD_M_WR_slr": 48, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 24, + "WTR_M": 24, "WTR_S": 6, "RFC1_slr": 468, "RFC2_slr": 312, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5200A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5200A.json index 7688520c..85b13eee 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5200A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5200A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 13, "CCD_L_WR_slr": 52, "CCD_L_WR2_slr": 26, + "CCD_M_slr": 13, + "CCD_M_WR_slr": 52, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 26, + "WTR_M": 26, "WTR_S": 7, "RFC1_slr": 507, "RFC2_slr": 338, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5600A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5600A.json index d9f181df..09418ff4 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5600A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-5600A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 14, "CCD_L_WR_slr": 56, "CCD_L_WR2_slr": 28, + "CCD_M_slr": 14, + "CCD_M_WR_slr": 56, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 28, + "WTR_M": 28, "WTR_S": 7, "RFC1_slr": 546, "RFC2_slr": 364, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6000A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6000A.json index a14606bd..420e23a5 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6000A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6000A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 15, "CCD_L_WR_slr": 60, "CCD_L_WR2_slr": 30, + "CCD_M_slr": 15, + "CCD_M_WR_slr": 60, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 30, + "WTR_M": 30, "WTR_S": 8, "RFC1_slr": 585, "RFC2_slr": 390, diff --git a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6400A.json b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6400A.json index 65d465fb..c8d3f989 100644 --- a/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6400A.json +++ b/configs/memspec/JEDEC_2x8x2Gbx4_DDR5-6400A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 16, "CCD_L_WR_slr": 64, "CCD_L_WR2_slr": 32, + "CCD_M_slr": 16, + "CCD_M_WR_slr": 64, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 0, @@ -50,6 +52,7 @@ "FAW_slr": 32, "FAW_dlr": 0, "WTR_L": 32, + "WTR_M": 32, "WTR_S": 8, "RFC1_slr": 624, "RFC2_slr": 416, diff --git a/configs/memspec/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json b/configs/memspec/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json index b8b0fd2a..caa01d4c 100644 --- a/configs/memspec/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json +++ b/configs/memspec/JEDEC_2x8x8x2Gbx4_DDR5-3200A.json @@ -39,6 +39,8 @@ "CCD_L_slr": 8, "CCD_L_WR_slr": 32, "CCD_L_WR2_slr": 16, + "CCD_M_slr": 8, + "CCD_M_WR_slr": 32, "CCD_S_slr": 8, "CCD_S_WR_slr": 8, "CCD_dlr": 8, @@ -49,7 +51,8 @@ "RRD_dlr": 4, "FAW_slr": 32, "FAW_dlr": 16, - "WTR_L": 16, + "WTR_L": 16, + "WTR_M": 16, "WTR_S": 4, "RFC1_slr": 312, "RFC2_slr": 208, diff --git a/extensions/apps/traceAnalyzer/simulationdialog.cpp b/extensions/apps/traceAnalyzer/simulationdialog.cpp index df72ec9a..6f72b807 100644 --- a/extensions/apps/traceAnalyzer/simulationdialog.cpp +++ b/extensions/apps/traceAnalyzer/simulationdialog.cpp @@ -217,7 +217,7 @@ void SimulationDialog::saveConfiguration(QFile &file) loadConfigurationFromTextFields(); - std::string dump = DRAMSys::Config::dump(configuration, 4); + std::string dump = nlohmann::json(configuration).dump(4); out << dump.c_str(); } @@ -252,13 +252,13 @@ void SimulationDialog::loadConfigurationFromTextFields() try { - from_dump(ui->addressMappingTextEdit->toPlainText().toStdString(), addressMapping); - from_dump(ui->mcConfigTextEdit->toPlainText().toStdString(), mcConfig); - from_dump(ui->memSpecTextEdit->toPlainText().toStdString(), memSpec); - from_dump(ui->simConfigTextEdit->toPlainText().toStdString(), simConfig); + nlohmann::json::parse(ui->addressMappingTextEdit->toPlainText().toStdString()).get_to(addressMapping); + nlohmann::json::parse(ui->mcConfigTextEdit->toPlainText().toStdString()).get_to(mcConfig); + nlohmann::json::parse(ui->memSpecTextEdit->toPlainText().toStdString()).get_to(memSpec); + nlohmann::json::parse(ui->simConfigTextEdit->toPlainText().toStdString()).get_to(simConfig); if (!ui->traceSetupTextEdit->toPlainText().toStdString().empty()) - from_dump(ui->traceSetupTextEdit->toPlainText().toStdString(), traceSetup); + nlohmann::json::parse(ui->traceSetupTextEdit->toPlainText().toStdString()).get_to(traceSetup); } catch (const std::exception &e) { @@ -300,9 +300,9 @@ void SimulationDialog::loadConfiguration() { ui->simulationIdLabel->setEnabled(true); ui->simulationId->setEnabled(true); - ui->simulationId->setText(configuration.simulationId.c_str()); + ui->simulationId->setText(configuration.simulationid.c_str()); - ui->simulationIdLineEdit->setText(configuration.simulationId.c_str()); + ui->simulationIdLineEdit->setText(configuration.simulationid.c_str()); loadSimConfig(); loadMcConfig(); @@ -316,7 +316,7 @@ void SimulationDialog::loadSimConfig() { ui->simConfigTextEdit->clear(); - std::string dump = DRAMSys::Config::dump(configuration.simConfig, 4); + std::string dump = nlohmann::json(configuration.simconfig).dump(4); ui->simConfigTextEdit->setText(dump.c_str()); } @@ -324,7 +324,7 @@ void SimulationDialog::loadMcConfig() { ui->mcConfigTextEdit->clear(); - std::string dump = DRAMSys::Config::dump(configuration.mcConfig, 4); + std::string dump = nlohmann::json(configuration.mcconfig).dump(4); ui->mcConfigTextEdit->setText(dump.c_str()); } @@ -332,7 +332,7 @@ void SimulationDialog::loadMemSpec() { ui->memSpecTextEdit->clear(); - std::string dump = DRAMSys::Config::dump(configuration.memSpec, 4); + std::string dump = nlohmann::json(configuration.memspec).dump(4); ui->memSpecTextEdit->setText(dump.c_str()); } @@ -340,7 +340,7 @@ void SimulationDialog::loadAddressMapping() { ui->addressMappingTextEdit->clear(); - std::string dump = DRAMSys::Config::dump(configuration.addressMapping, 4); + std::string dump = nlohmann::json(configuration.addressmapping).dump(4); ui->addressMappingTextEdit->setText(dump.c_str()); } @@ -348,9 +348,9 @@ void SimulationDialog::loadTraceSetup() { ui->traceSetupTextEdit->clear(); - if (const auto &traceSetup = configuration.traceSetup) + if (const auto &traceSetup = configuration.tracesetup) { - std::string dump = DRAMSys::Config::dump(*traceSetup, 4); + std::string dump = nlohmann::json(*traceSetup).dump(4); ui->traceSetupTextEdit->setText(dump.c_str()); } } @@ -359,7 +359,7 @@ void SimulationDialog::loadPreview() { ui->previewTextEdit->clear(); - std::string dump = DRAMSys::Config::dump(configuration, 4); + std::string dump = nlohmann::json(configuration).dump(4); ui->previewTextEdit->setText(dump.c_str()); } @@ -372,7 +372,7 @@ QFileInfoList SimulationDialog::getSimulationResults() for (const auto &fileInfo : baseDir.entryInfoList()) { - if (fileInfo.baseName().startsWith(configuration.simulationId.c_str())) + if (fileInfo.baseName().startsWith(configuration.simulationid.c_str())) { // Dont open tracefiles that are older than a few seconds if (fileInfo.metadataChangeTime().secsTo(QDateTime::currentDateTime()) > 30) diff --git a/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.cpp b/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.cpp index 1558946a..ab201a8d 100644 --- a/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.cpp +++ b/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.cpp @@ -45,77 +45,80 @@ using namespace tlm; MemSpecDDR5::MemSpecDDR5(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::DDR5, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - dimmRanksPerChannel(memSpec.memArchitectureSpec.entries.at("nbrOfDIMMRanks")), - physicalRanksPerDimmRank(memSpec.memArchitectureSpec.entries.at("nbrOfPhysicalRanks")), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + dimmRanksPerChannel(memSpec.memarchitecturespec.entries.at("nbrOfDIMMRanks")), + physicalRanksPerDimmRank(memSpec.memarchitecturespec.entries.at("nbrOfPhysicalRanks")), physicalRanksPerChannel(physicalRanksPerDimmRank * dimmRanksPerChannel), - logicalRanksPerPhysicalRank(memSpec.memArchitectureSpec.entries.at("nbrOfLogicalRanks")), + logicalRanksPerPhysicalRank(memSpec.memarchitecturespec.entries.at("nbrOfLogicalRanks")), logicalRanksPerChannel(logicalRanksPerPhysicalRank * physicalRanksPerChannel), - cmdMode(memSpec.memArchitectureSpec.entries.at("cmdMode")), - refMode(memSpec.memArchitectureSpec.entries.at("refMode")), - RAAIMT(memSpec.memArchitectureSpec.entries.at("RAAIMT")), - RAAMMT(memSpec.memArchitectureSpec.entries.at("RAAMMT")), - RAACDR(memSpec.memArchitectureSpec.entries.at("RAACDR")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), + cmdMode(memSpec.memarchitecturespec.entries.at("cmdMode")), + refMode(memSpec.memarchitecturespec.entries.at("refMode")), + RAAIMT(memSpec.memarchitecturespec.entries.at("RAAIMT")), + RAAMMT(memSpec.memarchitecturespec.entries.at("RAAMMT")), + RAACDR(memSpec.memarchitecturespec.entries.at("RAACDR")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), tRC (tRAS + tRP), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRPRE (tCK * memSpec.memTimingSpec.entries.at("RPRE")), - tRPST (tCK * memSpec.memTimingSpec.entries.at("RPST")), - tRDDQS (tCK * memSpec.memTimingSpec.entries.at("RDDQS")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWPRE (tCK * memSpec.memTimingSpec.entries.at("WPRE")), - tWPST (tCK * memSpec.memTimingSpec.entries.at("WPST")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tCCD_L_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_L_slr")), - tCCD_L_WR_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_L_WR_slr")), - tCCD_L_WR2_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_L_WR2_slr")), - tCCD_S_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_S_slr")), - tCCD_S_WR_slr (tCK * memSpec.memTimingSpec.entries.at("CCD_S_WR_slr")), - tCCD_dlr (tCK * memSpec.memTimingSpec.entries.at("CCD_dlr")), - tCCD_WR_dlr (tCK * memSpec.memTimingSpec.entries.at("CCD_WR_dlr")), - tCCD_WR_dpr (tCK * memSpec.memTimingSpec.entries.at("CCD_WR_dpr")), - tRRD_L_slr (tCK * memSpec.memTimingSpec.entries.at("RRD_L_slr")), - tRRD_S_slr (tCK * memSpec.memTimingSpec.entries.at("RRD_S_slr")), - tRRD_dlr (tCK * memSpec.memTimingSpec.entries.at("RRD_dlr")), - tFAW_slr (tCK * memSpec.memTimingSpec.entries.at("FAW_slr")), - tFAW_dlr (tCK * memSpec.memTimingSpec.entries.at("FAW_dlr")), - tWTR_L (tCK * memSpec.memTimingSpec.entries.at("WTR_L")), - tWTR_S (tCK * memSpec.memTimingSpec.entries.at("WTR_S")), - tRFC_slr ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("RFC1_slr") - : tCK * memSpec.memTimingSpec.entries.at("RFC2_slr")), - tRFC_dlr ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("RFC1_dlr") - : tCK * memSpec.memTimingSpec.entries.at("RFC2_dlr")), - tRFC_dpr ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("RFC1_dpr") - : tCK * memSpec.memTimingSpec.entries.at("RFC2_dpr")), - tRFCsb_slr (tCK * memSpec.memTimingSpec.entries.at("RFCsb_slr")), - tRFCsb_dlr (tCK * memSpec.memTimingSpec.entries.at("RFCsb_dlr")), - tREFI ((refMode == 1) ? tCK * memSpec.memTimingSpec.entries.at("REFI1") - : tCK * memSpec.memTimingSpec.entries.at("REFI2")), - tREFIsb (tCK * memSpec.memTimingSpec.entries.at("REFISB")), - tREFSBRD_slr (tCK * memSpec.memTimingSpec.entries.at("REFSBRD_slr")), - tREFSBRD_dlr (tCK * memSpec.memTimingSpec.entries.at("REFSBRD_dlr")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")), - tCPDED (tCK * memSpec.memTimingSpec.entries.at("CPDED")), - tPD (tCK * memSpec.memTimingSpec.entries.at("PD")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")), - tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")), - tREFPDEN (tCK * memSpec.memTimingSpec.entries.at("REFPDEN")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRPRE (tCK * memSpec.memtimingspec.entries.at("RPRE")), + tRPST (tCK * memSpec.memtimingspec.entries.at("RPST")), + tRDDQS (tCK * memSpec.memtimingspec.entries.at("RDDQS")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWPRE (tCK * memSpec.memtimingspec.entries.at("WPRE")), + tWPST (tCK * memSpec.memtimingspec.entries.at("WPST")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tCCD_L_slr (tCK * memSpec.memtimingspec.entries.at("CCD_L_slr")), + tCCD_L_WR_slr (tCK * memSpec.memtimingspec.entries.at("CCD_L_WR_slr")), + tCCD_L_WR2_slr (tCK * memSpec.memtimingspec.entries.at("CCD_L_WR2_slr")), + tCCD_M_slr (tCK * memSpec.memtimingspec.entries.at("CCD_M_slr")), + tCCD_M_WR_slr (tCK * memSpec.memtimingspec.entries.at("CCD_M_WR_slr")), + tCCD_S_slr (tCK * memSpec.memtimingspec.entries.at("CCD_S_slr")), + tCCD_S_WR_slr (tCK * memSpec.memtimingspec.entries.at("CCD_S_WR_slr")), + tCCD_dlr (tCK * memSpec.memtimingspec.entries.at("CCD_dlr")), + tCCD_WR_dlr (tCK * memSpec.memtimingspec.entries.at("CCD_WR_dlr")), + tCCD_WR_dpr (tCK * memSpec.memtimingspec.entries.at("CCD_WR_dpr")), + tRRD_L_slr (tCK * memSpec.memtimingspec.entries.at("RRD_L_slr")), + tRRD_S_slr (tCK * memSpec.memtimingspec.entries.at("RRD_S_slr")), + tRRD_dlr (tCK * memSpec.memtimingspec.entries.at("RRD_dlr")), + tFAW_slr (tCK * memSpec.memtimingspec.entries.at("FAW_slr")), + tFAW_dlr (tCK * memSpec.memtimingspec.entries.at("FAW_dlr")), + tWTR_L (tCK * memSpec.memtimingspec.entries.at("WTR_L")), + tWTR_M (tCK * memSpec.memtimingspec.entries.at("WTR_M")), + tWTR_S (tCK * memSpec.memtimingspec.entries.at("WTR_S")), + tRFC_slr ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("RFC1_slr") + : tCK * memSpec.memtimingspec.entries.at("RFC2_slr")), + tRFC_dlr ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("RFC1_dlr") + : tCK * memSpec.memtimingspec.entries.at("RFC2_dlr")), + tRFC_dpr ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("RFC1_dpr") + : tCK * memSpec.memtimingspec.entries.at("RFC2_dpr")), + tRFCsb_slr (tCK * memSpec.memtimingspec.entries.at("RFCsb_slr")), + tRFCsb_dlr (tCK * memSpec.memtimingspec.entries.at("RFCsb_dlr")), + tREFI ((refMode == 1) ? tCK * memSpec.memtimingspec.entries.at("REFI1") + : tCK * memSpec.memtimingspec.entries.at("REFI2")), + tREFIsb (tCK * memSpec.memtimingspec.entries.at("REFISB")), + tREFSBRD_slr (tCK * memSpec.memtimingspec.entries.at("REFSBRD_slr")), + tREFSBRD_dlr (tCK * memSpec.memtimingspec.entries.at("REFSBRD_dlr")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")), + tCPDED (tCK * memSpec.memtimingspec.entries.at("CPDED")), + tPD (tCK * memSpec.memtimingspec.entries.at("PD")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")), + tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")), + tREFPDEN (tCK * memSpec.memtimingspec.entries.at("REFPDEN")), shortCmdOffset (cmdMode == 2 ? 1 * tCK : 0 * tCK), longCmdOffset (cmdMode == 2 ? 3 * tCK : 1 * tCK), tBURST16 (tCK * 8), diff --git a/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.h b/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.h index 156d2a96..485d229b 100644 --- a/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.h +++ b/extensions/standards/DDR5/DRAMSys/configuration/memspec/MemSpecDDR5.h @@ -74,6 +74,8 @@ public: const sc_core::sc_time tCCD_L_slr; const sc_core::sc_time tCCD_L_WR_slr; const sc_core::sc_time tCCD_L_WR2_slr; + const sc_core::sc_time tCCD_M_slr; + const sc_core::sc_time tCCD_M_WR_slr; const sc_core::sc_time tCCD_S_slr; const sc_core::sc_time tCCD_S_WR_slr; const sc_core::sc_time tCCD_dlr; @@ -85,6 +87,7 @@ public: const sc_core::sc_time tFAW_slr; const sc_core::sc_time tFAW_dlr; const sc_core::sc_time tWTR_L; + const sc_core::sc_time tWTR_M; const sc_core::sc_time tWTR_S; const sc_core::sc_time tRFC_slr; const sc_core::sc_time tRFC_dlr; diff --git a/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.cpp b/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.cpp index c8d40f49..ffa12fe4 100644 --- a/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.cpp +++ b/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.cpp @@ -104,6 +104,7 @@ CheckerDDR5::CheckerDDR5(const Configuration& config) tRDWR_ddr = memSpec->tRL - memSpec->tWL + tBURST16 + memSpec->tRTRS - memSpec->tRDDQS + memSpec->tRPST + memSpec->tWPRE; tCCD_L_WTR_slr = memSpec->tWL + tBURST16 + memSpec->tWTR_L; + tCCD_M_WTR_slr = memSpec->tWL + tBURST16 + memSpec->tWTR_M; // tWTR_M is max(16nck, 10ns) tCCD_S_WTR_slr = memSpec->tWL + tBURST16 + memSpec->tWTR_S; tCCD_WTR_dlr = memSpec->tWL + tBURST16 + memSpec->tWTR_S; tWRWR_dpr = std::max(memSpec->tCCD_WR_dpr, tBURST16 + memSpec->tRTRS); @@ -140,10 +141,14 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, const tlm_generic if (lastCommandStart != scMaxTime) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); - lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankGroup.ID()]; + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; if (lastCommandStart != scMaxTime) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_slr); + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankGroup.ID()]; + if (lastCommandStart != scMaxTime) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_M_slr); + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RD][logicalRank.ID()]; if (lastCommandStart != scMaxTime) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S_slr); @@ -178,7 +183,7 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, const tlm_generic lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankGroup.ID()]; if (lastCommandStart != scMaxTime) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_slr); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_M_slr); lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::RDA][logicalRank.ID()]; if (lastCommandStart != scMaxTime) @@ -224,13 +229,22 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, const tlm_generic } } + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != scMaxTime) + { + if (lastBurstLengthByCommandAndBank[Command::WR][bank.ID()] == 32) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr + tBURST16); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + } + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankGroup.ID()]; if (lastCommandStart != scMaxTime) { if (lastBurstLengthByCommandAndBankGroup[Command::WR][bankGroup.ID()] == 32) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr + tBURST16); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_M_WTR_slr + tBURST16); else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_M_WTR_slr); } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WR][logicalRank.ID()]; @@ -274,9 +288,9 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, const tlm_generic if (lastCommandStart != scMaxTime) { if (lastBurstLengthByCommandAndBankGroup[Command::WRA][bankGroup.ID()] == 32) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr + tBURST16); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_M_WTR_slr + tBURST16); else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_L_WTR_slr); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tCCD_M_WTR_slr); } lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::WRA][logicalRank.ID()]; @@ -419,22 +433,47 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, const tlm_generic } } - lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankGroup.ID()]; - if (lastCommandStart != scMaxTime) + if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW { - if (lastBurstLengthByCommandAndBankGroup[Command::WR][bankGroup.ID()] == 32) + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != scMaxTime) { - if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW + if (lastBurstLengthByCommandAndBank[Command::WR][bank.ID()] == 32) + { earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR_slr); + } else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR2_slr); - } - else - { - if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW + { earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + } + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankGroup.ID()]; + if (lastCommandStart != lastScheduledByCommandAndBank[Command::WR][bank.ID()]) // different bank + { + if (lastBurstLengthByCommandAndBankGroup[Command::WR][bankGroup.ID()] == 32) + { + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_M_WR_slr); + } else + { + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_M_WR_slr); + } + } + } + else // no RMW + { + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankGroup.ID()]; + if (lastCommandStart != scMaxTime) + { + if (lastBurstLengthByCommandAndBankGroup[Command::WR][bankGroup.ID()] == 32) + { + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR2_slr); + } + else + { earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR2_slr); + } } } @@ -470,22 +509,34 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, const tlm_generic } } - lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankGroup.ID()]; - if (lastCommandStart != scMaxTime) + if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW { - if (lastBurstLengthByCommandAndBankGroup[Command::WRA][bankGroup.ID()] == 32) + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankGroup.ID()]; + if (lastCommandStart != scMaxTime) { - if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR_slr); + if (lastBurstLengthByCommandAndBankGroup[Command::WRA][bankGroup.ID()] == 32) + { + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_M_WR_slr); + } else - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR2_slr); + { + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_M_WR_slr); + } } - else + } + else // no RMW + { + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankGroup.ID()]; + if (lastCommandStart != scMaxTime) { - if (burstLength == 16 && memSpec->bitWidth == 4) // second WR requires RMW - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR_slr); + if (lastBurstLengthByCommandAndBankGroup[Command::WRA][bankGroup.ID()] == 32) + { + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST16 + memSpec->tCCD_L_WR2_slr); + } else + { earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L_WR2_slr); + } } } diff --git a/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.h b/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.h index 78c92ecf..8bc3311f 100644 --- a/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.h +++ b/extensions/standards/DDR5/DRAMSys/controller/checker/CheckerDDR5.h @@ -96,6 +96,7 @@ private: sc_core::sc_time tRDWR_dpr; sc_core::sc_time tRDWR_ddr; sc_core::sc_time tCCD_L_WTR_slr; + sc_core::sc_time tCCD_M_WTR_slr; sc_core::sc_time tCCD_S_WTR_slr; sc_core::sc_time tCCD_WTR_dlr; sc_core::sc_time tWRWR_dpr; diff --git a/extensions/standards/HBM3/DRAMSys/configuration/memspec/MemSpecHBM3.cpp b/extensions/standards/HBM3/DRAMSys/configuration/memspec/MemSpecHBM3.cpp index 7a4251c7..c717c23d 100644 --- a/extensions/standards/HBM3/DRAMSys/configuration/memspec/MemSpecHBM3.cpp +++ b/extensions/standards/HBM3/DRAMSys/configuration/memspec/MemSpecHBM3.cpp @@ -44,51 +44,51 @@ using namespace tlm; MemSpecHBM3::MemSpecHBM3(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::HBM3, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - RAAIMT(memSpec.memArchitectureSpec.entries.at("RAAIMT")), - RAAMMT(memSpec.memArchitectureSpec.entries.at("RAAMMT")), - RAACDR(memSpec.memArchitectureSpec.entries.at("RAACDR")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")), - tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")), - tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")), - tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tPL (tCK * memSpec.memTimingSpec.entries.at("PL")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")), - tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")), - tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")), - tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")), - tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + RAAIMT(memSpec.memarchitecturespec.entries.at("RAAIMT")), + RAAMMT(memSpec.memarchitecturespec.entries.at("RAAMMT")), + RAACDR(memSpec.memarchitecturespec.entries.at("RAACDR")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")), + tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")), + tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")), + tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tPL (tCK * memSpec.memtimingspec.entries.at("PL")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")), + tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")), + tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")), + tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")), + tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), tPD (tCKE), tCKESR (tCKE + tCK), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), - tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")), - tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")) + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")), + tRFCPB (tCK * memSpec.memtimingspec.entries.at("RFCPB")), + tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFIPB (tCK * memSpec.memtimingspec.entries.at("REFIPB")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")) { commandLengthInCycles[Command::ACT] = 1.5; commandLengthInCycles[Command::PREPB] = 0.5; diff --git a/extensions/standards/LPDDR5/DRAMSys/configuration/memspec/MemSpecLPDDR5.cpp b/extensions/standards/LPDDR5/DRAMSys/configuration/memspec/MemSpecLPDDR5.cpp index e805852c..7fb0469b 100644 --- a/extensions/standards/LPDDR5/DRAMSys/configuration/memspec/MemSpecLPDDR5.cpp +++ b/extensions/standards/LPDDR5/DRAMSys/configuration/memspec/MemSpecLPDDR5.cpp @@ -44,42 +44,42 @@ using namespace tlm; MemSpecLPDDR5::MemSpecLPDDR5(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::LPDDR5, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - per2BankOffset(memSpec.memArchitectureSpec.entries.at("per2BankOffset")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFIpb (tCK * memSpec.memTimingSpec.entries.at("REFIpb")), - tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCab")), - tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCpb")), - tRPab (tCK * memSpec.memTimingSpec.entries.at("RPab")), - tRPpb (tCK * memSpec.memTimingSpec.entries.at("RPpb")), - tRCab (tCK * memSpec.memTimingSpec.entries.at("RCab")), - tRCpb (tCK * memSpec.memTimingSpec.entries.at("RCpb")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRCD_L (tCK * memSpec.memTimingSpec.entries.at("RCD_L")), - tRCD_S (tCK * memSpec.memTimingSpec.entries.at("RCD_S")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + per2BankOffset(memSpec.memarchitecturespec.entries.at("per2BankOffset")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFIpb (tCK * memSpec.memtimingspec.entries.at("REFIpb")), + tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCab")), + tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCpb")), + tRPab (tCK * memSpec.memtimingspec.entries.at("RPab")), + tRPpb (tCK * memSpec.memtimingspec.entries.at("RPpb")), + tRCab (tCK * memSpec.memtimingspec.entries.at("RCab")), + tRCpb (tCK * memSpec.memtimingspec.entries.at("RCpb")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRCD_L (tCK * memSpec.memtimingspec.entries.at("RCD_L")), + tRCD_S (tCK * memSpec.memtimingspec.entries.at("RCD_S")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")), //tCCD (tCK * parseUint(memspec["memtimingspec"], "CCD")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), //tRPST (tCK * parseUint(memspec["memtimingspec"], "RPST")), //tDQSCK (tCK * parseUint(memspec["memtimingspec"], "DQSCK")), - tRBTP (tCK * memSpec.memTimingSpec.entries.at("RBTP")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), + tRBTP (tCK * memSpec.memtimingspec.entries.at("RBTP")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), //tDQSS (tCK * parseUint(memspec["memtimingspec"], "DQSS")), //tDQS2DQ (tCK * parseUint(memspec["memtimingspec"], "DQS2DQ")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), //tWPRE (tCK * parseUint(memspec["memtimingspec"], "WPRE")), //tWTR (tCK * parseUint(memspec["memtimingspec"], "WTR")), //tXP (tCK * parseUint(memspec["memtimingspec"] "XP")), @@ -88,20 +88,20 @@ MemSpecLPDDR5::MemSpecLPDDR5(const DRAMSys::Config::MemSpec &memSpec) //tESCKE (tCK * parseUint(memspec["memtimingspec"], "ESCKE")), //tCKE (tCK * parseUint(memspec["memtimingspec"], "CKE")), //tCMDCKE (tCK * parseUint(memspec["memtimingspec"], "CMDCKE")), - BL_n_min_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_min_16")), - BL_n_max_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_max_16")), - BL_n_L_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_L_16")), - BL_n_S_16(tCK * memSpec.memTimingSpec.entries.at("BL_n_S_16")), - BL_n_min_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_min_32")), - BL_n_max_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_max_32")), - BL_n_L_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_L_32")), - BL_n_S_32(tCK * memSpec.memTimingSpec.entries.at("BL_n_S_32")), - tWTR_L (tCK * memSpec.memTimingSpec.entries.at("WTR_L")), - tWTR_S (tCK * memSpec.memTimingSpec.entries.at("WTR_S")), - tWCK2DQO(tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")), - tpbR2act(tCK * memSpec.memTimingSpec.entries.at("pbR2act")), - tpbR2pbR(tCK * memSpec.memTimingSpec.entries.at("pbR2pbR")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")), + BL_n_min_16(tCK * memSpec.memtimingspec.entries.at("BL_n_min_16")), + BL_n_max_16(tCK * memSpec.memtimingspec.entries.at("BL_n_max_16")), + BL_n_L_16(tCK * memSpec.memtimingspec.entries.at("BL_n_L_16")), + BL_n_S_16(tCK * memSpec.memtimingspec.entries.at("BL_n_S_16")), + BL_n_min_32(tCK * memSpec.memtimingspec.entries.at("BL_n_min_32")), + BL_n_max_32(tCK * memSpec.memtimingspec.entries.at("BL_n_max_32")), + BL_n_L_32(tCK * memSpec.memtimingspec.entries.at("BL_n_L_32")), + BL_n_S_32(tCK * memSpec.memtimingspec.entries.at("BL_n_S_32")), + tWTR_L (tCK * memSpec.memtimingspec.entries.at("WTR_L")), + tWTR_S (tCK * memSpec.memtimingspec.entries.at("WTR_S")), + tWCK2DQO(tCK * memSpec.memtimingspec.entries.at("WCK2DQO")), + tpbR2act(tCK * memSpec.memtimingspec.entries.at("pbR2act")), + tpbR2pbR(tCK * memSpec.memtimingspec.entries.at("pbR2pbR")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")), tBURST16(tCK * 16 / dataRate), tBURST32(tCK * 32 / dataRate), bankMode(groupsPerRank != 1 ? BankMode::MBG : (banksPerRank == 16 ? BankMode::M16B : BankMode::M8B)) diff --git a/src/configuration/DRAMSys/config/AddressMapping.cpp b/src/configuration/DRAMSys/config/AddressMapping.cpp deleted file mode 100644 index 8123c88f..00000000 --- a/src/configuration/DRAMSys/config/AddressMapping.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2021, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Derek Christ - */ - -#include "AddressMapping.h" - -#include - -namespace DRAMSys::Config -{ - -void to_json(json_t &j, const AddressMapping &m) -{ - auto congen = json_t{{"BYTE_BIT", m.byteBits}, - {"COLUMN_BIT", m.columnBits}, - {"ROW_BIT", m.rowBits}, - {"BANK_BIT", m.bankBits}, - {"BANKGROUP_BIT", m.bankGroupBits}, - {"RANK_BIT", m.rankBits}, - {"CHANNEL_BIT", m.channelBits}, - {"XOR", m.xorBits}}; - - remove_null_values(congen); - - j["CONGEN"] = congen; -} - -void from_json(const json_t &j, AddressMapping &m) -{ - json_t j_addressmapping = get_config_json(j, addressMappingPath, "CONGEN"); - - json_t congen; - if (j_addressmapping["CONGEN"].is_null()) - congen = j_addressmapping; - else - congen = j_addressmapping["CONGEN"]; - - if (congen.contains("BYTE_BIT")) - congen.at("BYTE_BIT").get_to(m.byteBits); - - if (congen.contains("COLUMN_BIT")) - congen.at("COLUMN_BIT").get_to(m.columnBits); - - if (congen.contains("ROW_BIT")) - congen.at("ROW_BIT").get_to(m.rowBits); - - if (congen.contains("BANK_BIT")) - congen.at("BANK_BIT").get_to(m.bankBits); - - if (congen.contains("BANKGROUP_BIT")) - congen.at("BANKGROUP_BIT").get_to(m.bankGroupBits); - - if (congen.contains("RANK_BIT")) - congen.at("RANK_BIT").get_to(m.rankBits); - - // HBM pseudo channels are internally modelled as ranks - if (congen.contains("PSEUDOCHANNEL_BIT")) - congen.at("PSEUDOCHANNEL_BIT").get_to(m.rankBits); - - if (congen.contains("CHANNEL_BIT")) - congen.at("CHANNEL_BIT").get_to(m.channelBits); - - if (congen.contains("XOR")) - congen.at("XOR").get_to(m.xorBits); -} - -void to_json(json_t &j, const XorPair &x) -{ - j = json_t{{"FIRST", x.first}, {"SECOND", x.second}}; -} - -void from_json(const json_t &j, XorPair &x) -{ - j.at("FIRST").get_to(x.first); - j.at("SECOND").get_to(x.second); -} - -void from_dump(const std::string &dump, AddressMapping &c) -{ - json_t json_addressmapping = json_t::parse(dump).at("addressmapping"); - json_addressmapping.get_to(c); -} - -std::string dump(const AddressMapping &c, unsigned int indentation) -{ - json_t json_addressmapping; - json_addressmapping["addressmapping"] = c; - return json_addressmapping.dump(indentation); -} - -} // namespace DRAMSys::Config diff --git a/src/configuration/DRAMSys/config/AddressMapping.h b/src/configuration/DRAMSys/config/AddressMapping.h index 4426ff8d..53d285ef 100644 --- a/src/configuration/DRAMSys/config/AddressMapping.h +++ b/src/configuration/DRAMSys/config/AddressMapping.h @@ -36,40 +36,47 @@ #ifndef DRAMSYSCONFIGURATION_ADDRESSMAPPING_H #define DRAMSYSCONFIGURATION_ADDRESSMAPPING_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include namespace DRAMSys::Config { -const std::string addressMappingPath = "addressmapping"; struct XorPair { - unsigned int first; - unsigned int second; + unsigned int FIRST; + unsigned int SECOND; }; -void to_json(json_t &j, const XorPair &x); -void from_json(const json_t &j, XorPair &x); +NLOHMANN_JSONIFY_ALL_THINGS(XorPair, FIRST, SECOND) struct AddressMapping { - std::optional> byteBits; - std::optional> columnBits; - std::optional> rowBits; - std::optional> bankBits; - std::optional> bankGroupBits; - std::optional> rankBits; - std::optional> channelBits; - std::optional> xorBits; + static constexpr std::string_view KEY = "addressmapping"; + static constexpr std::string_view SUB_DIR = "addressmapping"; + + std::optional> BYTE_BIT; + std::optional> COLUMN_BIT; + std::optional> ROW_BIT; + std::optional> BANK_BIT; + std::optional> BANKGROUP_BIT; + std::optional> RANK_BIT; + std::optional> PSEUDOCHANNEL_BIT; + std::optional> CHANNEL_BIT; + std::optional> XOR; }; -void to_json(json_t &j, const AddressMapping &m); -void from_json(const json_t &j, AddressMapping &m); - -void from_dump(const std::string &dump, AddressMapping &c); -std::string dump(const AddressMapping &c, unsigned int indentation = -1); +NLOHMANN_JSONIFY_ALL_THINGS(AddressMapping, + BYTE_BIT, + COLUMN_BIT, + ROW_BIT, + BANK_BIT, + BANKGROUP_BIT, + RANK_BIT, + PSEUDOCHANNEL_BIT, + CHANNEL_BIT, + XOR) } // namespace Configuration diff --git a/src/configuration/DRAMSys/config/ConfigUtil.h b/src/configuration/DRAMSys/config/ConfigUtil.h deleted file mode 100644 index 9c45aa5b..00000000 --- a/src/configuration/DRAMSys/config/ConfigUtil.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2021, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Derek Christ - */ - -#ifndef DRAMSYSCONFIGURATION_UTIL_H -#define DRAMSYSCONFIGURATION_UTIL_H - -#include "DRAMSys/util/json.h" - -#include -#include - -namespace DRAMSys::Config -{ - //using json_t = nlohmann::json; - - // template - // class Optional : public std::pair - // { - // public: - // Optional() : std::pair{{}, false} - // { - // } - // Optional(const T &v) : std::pair{v, true} - // { - // } - - // bool isValid() const - // { - // return this->second; - // } - - // const T &getValue() const - // { - // assert(this->second == true); - // return this->first; - // } - - // void setValue(const T &v) - // { - // this->first = v; - // this->second = true; - // } - - // void invalidate() - // { - // this->second = false; - // } - - // /** - // * This methods only purpose is to make a optional type - // * valid so that it can be written to by reference. - // */ - // T &setByReference() - // { - // this->second = true; - // return this->first; - // } - // }; - - template - void invalidateEnum(T& value) - { - if (value.has_value() && value.value() == T::value_type::Invalid) - value.reset(); - } - - json_t get_config_json(const json_t& j, const std::string& configPath, const std::string& objectName); - - inline void remove_null_values(json_t& j) - { - std::vector keysToRemove; - - for (const auto& element : j.items()) - { - if (element.value() == nullptr) - keysToRemove.emplace_back(element.key()); - } - - std::for_each(keysToRemove.begin(), keysToRemove.end(), [&](const std::string& key) { j.erase(key); }); - } - -} // namespace DRAMSys::Config - -#endif // DRAMSYSCONFIGURATION_UTIL_H diff --git a/src/configuration/DRAMSys/config/DRAMSysConfiguration.cpp b/src/configuration/DRAMSys/config/DRAMSysConfiguration.cpp index c93f9002..324929fd 100644 --- a/src/configuration/DRAMSys/config/DRAMSysConfiguration.cpp +++ b/src/configuration/DRAMSys/config/DRAMSysConfiguration.cpp @@ -35,62 +35,97 @@ #include "DRAMSysConfiguration.h" -#include "DRAMSys/config/ConfigUtil.h" - #include +#include namespace DRAMSys::Config { -std::string Configuration::resourceDirectory; - -void to_json(json_t &j, const Configuration &c) +Configuration from_path(std::string_view path, std::string_view resourceDirectory) { - j = json_t{{"addressmapping", c.addressMapping}, {"mcconfig", c.mcConfig}, {"memspec", c.memSpec}, - {"simulationid", c.simulationId}, {"simconfig", c.simConfig}, {"tracesetup", c.traceSetup}}; + std::ifstream file(path.data()); - remove_null_values(j); -} - -void from_json(const json_t &j, Configuration &c) -{ - j.at("addressmapping").get_to(c.addressMapping); - j.at("mcconfig").get_to(c.mcConfig); - j.at("memspec").get_to(c.memSpec); - j.at("simulationid").get_to(c.simulationId); - j.at("simconfig").get_to(c.simConfig); - - if (j.contains("tracesetup")) - j.at("tracesetup").get_to(c.traceSetup); -} - -void from_dump(const std::string &dump, Configuration &c) -{ - json_t json_simulation = json_t::parse(dump).at("simulation"); - json_simulation.get_to(c); -} - -std::string dump(const Configuration &c, unsigned int indentation) -{ - json_t json_simulation; - json_simulation["simulation"] = c; - return json_simulation.dump(indentation); -} - -Configuration from_path(const std::string &path, const std::string &resourceDirectory) -{ - Configuration::resourceDirectory = resourceDirectory; - - std::ifstream file(path); - - if (file.is_open()) + enum class SubConfig { - json_t simulation = json_t::parse(file).at("simulation"); + MemSpec, + AddressMapping, + McConfig, + SimConfig, + TraceSetup, + Unkown + } current_sub_config; + + // This custom parser callback is responsible to swap out the paths to the sub-config json files + // with the actual json data. + std::function + parser_callback; + parser_callback = + [&parser_callback, ¤t_sub_config, resourceDirectory]( + int depth, nlohmann::detail::parse_event_t event, json_t &parsed) -> bool { + using nlohmann::detail::parse_event_t; + + if (depth != 2) + return true; + + if (event == parse_event_t::key) { + assert(parsed.is_string()); + + if (parsed == MemSpec::KEY) + current_sub_config = SubConfig::MemSpec; + else if (parsed == AddressMapping::KEY) + current_sub_config = SubConfig::AddressMapping; + else if (parsed == McConfig::KEY) + current_sub_config = SubConfig::McConfig; + else if (parsed == SimConfig::KEY) + current_sub_config = SubConfig::SimConfig; + else if (parsed == TraceSetupConstants::KEY) + current_sub_config = SubConfig::TraceSetup; + else + current_sub_config = SubConfig::Unkown; + } + + // In case we have an value (string) instead of an object, replace the value with the loaded + // json object. + if (event == parse_event_t::value && current_sub_config != SubConfig::Unkown) { + // Replace name of json file with actual json data + auto parse_json = [&parser_callback, + resourceDirectory](std::string_view base_dir, + std::string_view sub_config_key, + const std::string &filename) -> json_t { + std::filesystem::path path(resourceDirectory); + path /= base_dir; + path /= filename; + + std::ifstream json_file(path); + + if (!json_file.is_open()) + throw std::runtime_error("Failed to open file " + std::string(path)); + + json_t json = + json_t::parse(json_file, parser_callback, true, true).at(sub_config_key); + return json; + }; + + if (current_sub_config == SubConfig::MemSpec) + parsed = parse_json(MemSpec::SUB_DIR, MemSpec::KEY, parsed); + else if (current_sub_config == SubConfig::AddressMapping) + parsed = parse_json(AddressMapping::SUB_DIR, AddressMapping::KEY, parsed); + else if (current_sub_config == SubConfig::McConfig) + parsed = parse_json(McConfig::SUB_DIR, McConfig::KEY, parsed); + else if (current_sub_config == SubConfig::SimConfig) + parsed = parse_json(SimConfig::SUB_DIR, SimConfig::KEY, parsed); + else if (current_sub_config == SubConfig::TraceSetup) + parsed = parse_json(TraceSetupConstants::SUB_DIR, TraceSetupConstants::KEY, parsed); + } + + return true; + }; + + if (file.is_open()) { + json_t simulation = json_t::parse(file, parser_callback, true, true).at(Configuration::KEY); return simulation.get(); - } - else - { - throw std::runtime_error("Failed to open file " + path); + } else { + throw std::runtime_error("Failed to open file " + std::string(path)); } } diff --git a/src/configuration/DRAMSys/config/DRAMSysConfiguration.h b/src/configuration/DRAMSys/config/DRAMSysConfiguration.h index 2f2e4e52..ada4f444 100644 --- a/src/configuration/DRAMSys/config/DRAMSysConfiguration.h +++ b/src/configuration/DRAMSys/config/DRAMSysConfiguration.h @@ -41,42 +41,45 @@ #include "DRAMSys/config/SimConfig.h" #include "DRAMSys/config/TraceSetup.h" #include "DRAMSys/config/memspec/MemSpec.h" -#include "DRAMSys/config/ConfigUtil.h" #include #include /** - * To support polymorphic configurations, a Json "type" tag is used - * to determine the correct type before further parsing. - * * To support optional values, std::optional is used. The default * values will be provided by DRAMSys itself. * - * To achieve static polymorphism, std::variant is used. + * To achieve static polymorphism, std::variant is used. The concrete + * type is determined by the provided fields automatically. + * + * To achieve backwards compatibility, this library manipulates the json + * data type as it is parsed in to substitute paths to sub-configurations + * with the actual json object that is stored at this path. */ namespace DRAMSys::Config { struct Configuration { - AddressMapping addressMapping; - McConfig mcConfig; - MemSpec memSpec; - SimConfig simConfig; - std::string simulationId; - std::optional traceSetup; - - static std::string resourceDirectory; + static constexpr std::string_view KEY = "simulation"; + + AddressMapping addressmapping; + McConfig mcconfig; + MemSpec memspec; + SimConfig simconfig; + std::string simulationid; + std::optional tracesetup; }; -void to_json(json &j, const Configuration &p); -void from_json(const json &j, Configuration &p); +NLOHMANN_JSONIFY_ALL_THINGS(Configuration, + addressmapping, + mcconfig, + memspec, + simconfig, + simulationid, + tracesetup) -void from_dump(const std::string &dump, Configuration &c); -std::string dump(const Configuration &c, unsigned int indentation = -1); - -Configuration from_path(const std::string &path, const std::string &resourceDirectory = DRAMSYS_RESOURCE_DIR); +Configuration from_path(std::string_view path, std::string_view resourceDirectory = DRAMSYS_RESOURCE_DIR); } // namespace DRAMSys::Config diff --git a/src/configuration/DRAMSys/config/McConfig.cpp b/src/configuration/DRAMSys/config/McConfig.cpp index ff9f479d..6017fe1c 100644 --- a/src/configuration/DRAMSys/config/McConfig.cpp +++ b/src/configuration/DRAMSys/config/McConfig.cpp @@ -38,162 +38,36 @@ namespace DRAMSys::Config { -void to_json(json_t &j, const McConfig &c) +void to_json(json_t &j, const RefreshPolicyType &r) { - j = json_t{{"PagePolicy", c.pagePolicy}, - {"Scheduler", c.scheduler}, - {"HighWatermark", c.highWatermark}, - {"LowWatermark", c.lowWatermark}, - {"SchedulerBuffer", c.schedulerBuffer}, - {"RequestBufferSize", c.requestBufferSize}, - {"CmdMux", c.cmdMux}, - {"RespQueue", c.respQueue}, - {"RefreshPolicy", c.refreshPolicy}, - {"RefreshMaxPostponed", c.refreshMaxPostponed}, - {"RefreshMaxPulledin", c.refreshMaxPulledin}, - {"PowerDownPolicy", c.powerDownPolicy}, - {"Arbiter", c.arbiter}, - {"MaxActiveTransactions", c.maxActiveTransactions}, - {"RefreshManagement", c.refreshManagement}, - {"ArbitrationDelayFw", c.arbitrationDelayFw}, - {"ArbitrationDelayBw", c.arbitrationDelayBw}, - {"ThinkDelayFw", c.thinkDelayFw}, - {"ThinkDelayBw", c.thinkDelayBw}, - {"PhyDelayFw", c.phyDelayFw}, - {"PhyDelayBw", c.phyDelayBw}, - {"BlockingReadDelay", c.blockingReadDelay}, - {"BlockingWriteDelay", c.blockingWriteDelay}}; - - remove_null_values(j); -} - -void from_json(const json_t &j, McConfig &c) -{ - json_t j_mcconfig = get_config_json(j, mcConfigPath, "mcconfig"); - - if (j_mcconfig.contains("PagePolicy")) - j_mcconfig.at("PagePolicy").get_to(c.pagePolicy); - - if (j_mcconfig.contains("Scheduler")) - j_mcconfig.at("Scheduler").get_to(c.scheduler); - - if (j_mcconfig.contains("HighWatermark")) - j_mcconfig.at("HighWatermark").get_to(c.highWatermark); - - if (j_mcconfig.contains("LowWatermark")) - j_mcconfig.at("LowWatermark").get_to(c.lowWatermark); - - if (j_mcconfig.contains("SchedulerBuffer")) - j_mcconfig.at("SchedulerBuffer").get_to(c.schedulerBuffer); - - if (j_mcconfig.contains("RequestBufferSize")) - j_mcconfig.at("RequestBufferSize").get_to(c.requestBufferSize); - - if (j_mcconfig.contains("CmdMux")) - j_mcconfig.at("CmdMux").get_to(c.cmdMux); - - if (j_mcconfig.contains("RespQueue")) - j_mcconfig.at("RespQueue").get_to(c.respQueue); - - if (j_mcconfig.contains("RefreshPolicy")) - j_mcconfig.at("RefreshPolicy").get_to(c.refreshPolicy); - - if (j_mcconfig.contains("RefreshMaxPostponed")) - j_mcconfig.at("RefreshMaxPostponed").get_to(c.refreshMaxPostponed); - - if (j_mcconfig.contains("RefreshMaxPulledin")) - j_mcconfig.at("RefreshMaxPulledin").get_to(c.refreshMaxPulledin); - - if (j_mcconfig.contains("PowerDownPolicy")) - j_mcconfig.at("PowerDownPolicy").get_to(c.powerDownPolicy); - - if (j_mcconfig.contains("Arbiter")) - j_mcconfig.at("Arbiter").get_to(c.arbiter); - - if (j_mcconfig.contains("MaxActiveTransactions")) - j_mcconfig.at("MaxActiveTransactions").get_to(c.maxActiveTransactions); - - if (j_mcconfig.contains("RefreshManagement")) - j_mcconfig.at("RefreshManagement").get_to(c.refreshManagement); - - if (j_mcconfig.contains("ArbitrationDelayFw")) - j_mcconfig.at("ArbitrationDelayFw").get_to(c.arbitrationDelayFw); - - if (j_mcconfig.contains("ArbitrationDelayBw")) - j_mcconfig.at("ArbitrationDelayBw").get_to(c.arbitrationDelayBw); - - if (j_mcconfig.contains("ThinkDelayFw")) - j_mcconfig.at("ThinkDelayFw").get_to(c.thinkDelayFw); - - if (j_mcconfig.contains("ThinkDelayBw")) - j_mcconfig.at("ThinkDelayBw").get_to(c.thinkDelayBw); - - if (j_mcconfig.contains("PhyDelayFw")) - j_mcconfig.at("PhyDelayFw").get_to(c.phyDelayFw); - - if (j_mcconfig.contains("PhyDelayBw")) - j_mcconfig.at("PhyDelayBw").get_to(c.phyDelayBw); - - if (j_mcconfig.contains("BlockingReadDelay")) - j_mcconfig.at("BlockingReadDelay").get_to(c.blockingReadDelay); - - if (j_mcconfig.contains("BlockingWriteDelay")) - j_mcconfig.at("BlockingWriteDelay").get_to(c.blockingWriteDelay); - - invalidateEnum(c.pagePolicy); - invalidateEnum(c.scheduler); - invalidateEnum(c.schedulerBuffer); - invalidateEnum(c.cmdMux); - invalidateEnum(c.respQueue); - invalidateEnum(c.refreshPolicy); - invalidateEnum(c.respQueue); - invalidateEnum(c.powerDownPolicy); - invalidateEnum(c.arbiter); -} - -void to_json(json_t &j, const RefreshPolicy &r) -{ - if (r == RefreshPolicy::NoRefresh) + if (r == RefreshPolicyType::NoRefresh) j = "NoRefresh"; - else if (r == RefreshPolicy::AllBank) + else if (r == RefreshPolicyType::AllBank) j = "AllBank"; - else if (r == RefreshPolicy::PerBank) + else if (r == RefreshPolicyType::PerBank) j = "PerBank"; - else if (r == RefreshPolicy::Per2Bank) + else if (r == RefreshPolicyType::Per2Bank) j = "Per2Bank"; - else if (r == RefreshPolicy::SameBank) + else if (r == RefreshPolicyType::SameBank) j = "SameBank"; else j = nullptr; } -void from_json(const json_t &j, RefreshPolicy &r) +void from_json(const json_t &j, RefreshPolicyType &r) { if (j == "NoRefresh") - r = RefreshPolicy::NoRefresh; + r = RefreshPolicyType::NoRefresh; else if (j == "AllBank" || j == "Rankwise") - r = RefreshPolicy::AllBank; + r = RefreshPolicyType::AllBank; else if (j == "PerBank" || j == "Bankwise") - r = RefreshPolicy::PerBank; + r = RefreshPolicyType::PerBank; else if (j == "SameBank" || j == "Groupwise") - r = RefreshPolicy::SameBank; + r = RefreshPolicyType::SameBank; else if (j == "Per2Bank") - r = RefreshPolicy::Per2Bank; + r = RefreshPolicyType::Per2Bank; else - r = RefreshPolicy::Invalid; -} - -void from_dump(const std::string &dump, McConfig &c) -{ - json_t json_mcconfig = json_t::parse(dump).at("mcconfig"); - json_mcconfig.get_to(c); -} - -std::string dump(const McConfig &c, unsigned int indentation) -{ - json_t json_mcconfig; - json_mcconfig["mcconfig"] = c; - return json_mcconfig.dump(indentation); + r = RefreshPolicyType::Invalid; } } // namespace DRAMSys::Config diff --git a/src/configuration/DRAMSys/config/McConfig.h b/src/configuration/DRAMSys/config/McConfig.h index da697981..79437024 100644 --- a/src/configuration/DRAMSys/config/McConfig.h +++ b/src/configuration/DRAMSys/config/McConfig.h @@ -36,7 +36,7 @@ #ifndef DRAMSYSCONFIGURATION_MCCONFIG_H #define DRAMSYSCONFIGURATION_MCCONFIG_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include #include @@ -44,9 +44,8 @@ namespace DRAMSys::Config { -const std::string mcConfigPath = "mcconfig"; -enum class PagePolicy +enum class PagePolicyType { Open, OpenAdaptive, @@ -55,15 +54,15 @@ enum class PagePolicy Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(PagePolicy, { - {PagePolicy::Invalid, nullptr}, - {PagePolicy::Open, "Open"}, - {PagePolicy::OpenAdaptive, "OpenAdaptive"}, - {PagePolicy::Closed, "Closed"}, - {PagePolicy::ClosedAdaptive, "ClosedAdaptive"}, +NLOHMANN_JSON_SERIALIZE_ENUM(PagePolicyType, { + {PagePolicyType::Invalid, nullptr}, + {PagePolicyType::Open, "Open"}, + {PagePolicyType::OpenAdaptive, "OpenAdaptive"}, + {PagePolicyType::Closed, "Closed"}, + {PagePolicyType::ClosedAdaptive, "ClosedAdaptive"}, }) -enum class Scheduler +enum class SchedulerType { Fifo, FrFcfs, @@ -73,14 +72,14 @@ enum class Scheduler Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(Scheduler, {{Scheduler::Invalid, nullptr}, - {Scheduler::Fifo, "Fifo"}, - {Scheduler::FrFcfs, "FrFcfs"}, - {Scheduler::FrFcfsGrp, "FrFcfsGrp"}, - {Scheduler::GrpFrFcfs, "GrpFrFcfs"}, - {Scheduler::GrpFrFcfsWm, "GrpFrFcfsWm"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(SchedulerType, {{SchedulerType::Invalid, nullptr}, + {SchedulerType::Fifo, "Fifo"}, + {SchedulerType::FrFcfs, "FrFcfs"}, + {SchedulerType::FrFcfsGrp, "FrFcfsGrp"}, + {SchedulerType::GrpFrFcfs, "GrpFrFcfs"}, + {SchedulerType::GrpFrFcfsWm, "GrpFrFcfsWm"}}) -enum class SchedulerBuffer +enum class SchedulerBufferType { Bankwise, ReadWrite, @@ -88,33 +87,33 @@ enum class SchedulerBuffer Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(SchedulerBuffer, {{SchedulerBuffer::Invalid, nullptr}, - {SchedulerBuffer::Bankwise, "Bankwise"}, - {SchedulerBuffer::ReadWrite, "ReadWrite"}, - {SchedulerBuffer::Shared, "Shared"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(SchedulerBufferType, {{SchedulerBufferType::Invalid, nullptr}, + {SchedulerBufferType::Bankwise, "Bankwise"}, + {SchedulerBufferType::ReadWrite, "ReadWrite"}, + {SchedulerBufferType::Shared, "Shared"}}) -enum class CmdMux +enum class CmdMuxType { Oldest, Strict, Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(CmdMux, - {{CmdMux::Invalid, nullptr}, {CmdMux::Oldest, "Oldest"}, {CmdMux::Strict, "Strict"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(CmdMuxType, + {{CmdMuxType::Invalid, nullptr}, {CmdMuxType::Oldest, "Oldest"}, {CmdMuxType::Strict, "Strict"}}) -enum class RespQueue +enum class RespQueueType { Fifo, Reorder, Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(RespQueue, {{RespQueue::Invalid, nullptr}, - {RespQueue::Fifo, "Fifo"}, - {RespQueue::Reorder, "Reorder"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(RespQueueType, {{RespQueueType::Invalid, nullptr}, + {RespQueueType::Fifo, "Fifo"}, + {RespQueueType::Reorder, "Reorder"}}) -enum class RefreshPolicy +enum class RefreshPolicyType { NoRefresh, AllBank, @@ -124,18 +123,18 @@ enum class RefreshPolicy Invalid = -1 }; -enum class PowerDownPolicy +enum class PowerDownPolicyType { NoPowerDown, Staggered, Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(PowerDownPolicy, {{PowerDownPolicy::Invalid, nullptr}, - {PowerDownPolicy::NoPowerDown, "NoPowerDown"}, - {PowerDownPolicy::Staggered, "Staggered"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(PowerDownPolicyType, {{PowerDownPolicyType::Invalid, nullptr}, + {PowerDownPolicyType::NoPowerDown, "NoPowerDown"}, + {PowerDownPolicyType::Staggered, "Staggered"}}) -enum class Arbiter +enum class ArbiterType { Simple, Fifo, @@ -143,46 +142,71 @@ enum class Arbiter Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(Arbiter, {{Arbiter::Invalid, nullptr}, - {Arbiter::Simple, "Simple"}, - {Arbiter::Fifo, "Fifo"}, - {Arbiter::Reorder, "Reorder"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(ArbiterType, {{ArbiterType::Invalid, nullptr}, + {ArbiterType::Simple, "Simple"}, + {ArbiterType::Fifo, "Fifo"}, + {ArbiterType::Reorder, "Reorder"}}) struct McConfig { - std::optional pagePolicy; - std::optional scheduler; - std::optional highWatermark; - std::optional lowWatermark; - std::optional schedulerBuffer; - std::optional requestBufferSize; - std::optional cmdMux; - std::optional respQueue; - std::optional refreshPolicy; - std::optional refreshMaxPostponed; - std::optional refreshMaxPulledin; - std::optional powerDownPolicy; - std::optional arbiter; - std::optional maxActiveTransactions; - std::optional refreshManagement; - std::optional arbitrationDelayFw; - std::optional arbitrationDelayBw; - std::optional thinkDelayFw; - std::optional thinkDelayBw; - std::optional phyDelayFw; - std::optional phyDelayBw; - std::optional blockingReadDelay; - std::optional blockingWriteDelay; + static constexpr std::string_view KEY = "mcconfig"; + static constexpr std::string_view SUB_DIR = "mcconfig"; + + std::optional PagePolicy; + std::optional Scheduler; + std::optional HighWatermark; + std::optional LowWatermark; + std::optional SchedulerBuffer; + std::optional RequestBufferSize; + std::optional CmdMux; + std::optional RespQueue; + std::optional RefreshPolicy; + std::optional RefreshMaxPostponed; + std::optional RefreshMaxPulledin; + std::optional PowerDownPolicy; + std::optional Arbiter; + std::optional MaxActiveTransactions; + std::optional RefreshManagement; + std::optional ArbitrationDelayFw; + std::optional ArbitrationDelayBw; + std::optional ThinkDelayFw; + std::optional ThinkDelayBw; + std::optional PhyDelayFw; + std::optional PhyDelayBw; + std::optional BlockingReadDelay; + std::optional BlockingWriteDelay; }; -void to_json(json_t &j, const McConfig &c); -void from_json(const json_t &j, McConfig &c); +NLOHMANN_JSONIFY_ALL_THINGS(McConfig, + PagePolicy, + Scheduler, + HighWatermark, + LowWatermark, + SchedulerBuffer, + RequestBufferSize, + CmdMux, + RespQueue, + RefreshPolicy, + RefreshMaxPostponed, + RefreshMaxPulledin, + PowerDownPolicy, + Arbiter, + MaxActiveTransactions, + RefreshManagement, + ArbitrationDelayFw, + ArbitrationDelayBw, + ThinkDelayFw, + ThinkDelayBw, + PhyDelayFw, + PhyDelayBw, + BlockingReadDelay, + BlockingWriteDelay) -void to_json(json_t &j, const RefreshPolicy &r); -void from_json(const json_t &j, RefreshPolicy &r); +void to_json(json_t &j, const RefreshPolicyType &r); +void from_json(const json_t &j, RefreshPolicyType &r); -void from_dump(const std::string &dump, McConfig &c); -std::string dump(const McConfig &c, unsigned int indentation = -1); +// void from_dump(const std::string &dump, McConfig &c); +// std::string dump(const McConfig &c, unsigned int indentation = -1); } // namespace Configuration diff --git a/src/configuration/DRAMSys/config/SimConfig.cpp b/src/configuration/DRAMSys/config/SimConfig.cpp deleted file mode 100644 index 83d89ca8..00000000 --- a/src/configuration/DRAMSys/config/SimConfig.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2021, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Derek Christ - */ - -#include "SimConfig.h" - -namespace DRAMSys::Config -{ - -void to_json(json_t &j, const SimConfig &c) -{ - j = json_t{{"AddressOffset", c.addressOffset}, - {"CheckTLM2Protocol", c.checkTLM2Protocol}, - {"DatabaseRecording", c.databaseRecording}, - {"Debug", c.debug}, - {"EnableWindowing", c.enableWindowing}, - {"ErrorCSVFile", c.errorCsvFile}, - {"ErrorChipSeed", c.errorChipSeed}, - {"PowerAnalysis", c.powerAnalysis}, - {"SimulationName", c.simulationName}, - {"SimulationProgressBar", c.simulationProgressBar}, - {"StoreMode", c.storeMode}, - {"ThermalSimulation", c.thermalSimulation}, - {"UseMalloc", c.useMalloc}, - {"WindowSize", c.windowSize}}; -} - -void from_json(const json_t &j, SimConfig &c) -{ - json_t j_simconfig = get_config_json(j, simConfigPath, "simconfig"); - - if (j_simconfig.contains("AddressOffset")) - j_simconfig.at("AddressOffset").get_to(c.addressOffset); - - if (j_simconfig.contains("CheckTLM2Protocol")) - j_simconfig.at("CheckTLM2Protocol").get_to(c.checkTLM2Protocol); - - if (j_simconfig.contains("DatabaseRecording")) - j_simconfig.at("DatabaseRecording").get_to(c.databaseRecording); - - if (j_simconfig.contains("Debug")) - j_simconfig.at("Debug").get_to(c.debug); - - if (j_simconfig.contains("EnableWindowing")) - j_simconfig.at("EnableWindowing").get_to(c.enableWindowing); - - if (j_simconfig.contains("ErrorCSVFile")) - j_simconfig.at("ErrorCSVFile").get_to(c.errorCsvFile); - - if (j_simconfig.contains("ErrorChipSeed")) - j_simconfig.at("ErrorChipSeed").get_to(c.errorChipSeed); - - if (j_simconfig.contains("PowerAnalysis")) - j_simconfig.at("PowerAnalysis").get_to(c.powerAnalysis); - - if (j_simconfig.contains("SimulationName")) - j_simconfig.at("SimulationName").get_to(c.simulationName); - - if (j_simconfig.contains("SimulationProgressBar")) - j_simconfig.at("SimulationProgressBar").get_to(c.simulationProgressBar); - - if (j_simconfig.contains("StoreMode")) - j_simconfig.at("StoreMode").get_to(c.storeMode); - - if (j_simconfig.contains("ThermalSimulation")) - j_simconfig.at("ThermalSimulation").get_to(c.thermalSimulation); - - if (j_simconfig.contains("UseMalloc")) - j_simconfig.at("UseMalloc").get_to(c.useMalloc); - - if (j_simconfig.contains("WindowSize")) - j_simconfig.at("WindowSize").get_to(c.windowSize); - - invalidateEnum(c.storeMode); -} - -void from_dump(const std::string &dump, SimConfig &c) -{ - json_t json_simconfig = json_t::parse(dump).at("simconfig"); - json_simconfig.get_to(c); -} - -std::string dump(const SimConfig &c, unsigned int indentation) -{ - json_t json_simconfig; - json_simconfig["simconfig"] = c; - return json_simconfig.dump(indentation); -} - -} // namespace DRAMSys::Config diff --git a/src/configuration/DRAMSys/config/SimConfig.h b/src/configuration/DRAMSys/config/SimConfig.h index 5dee2443..a05da277 100644 --- a/src/configuration/DRAMSys/config/SimConfig.h +++ b/src/configuration/DRAMSys/config/SimConfig.h @@ -36,15 +36,14 @@ #ifndef DRAMSYSCONFIGURATION_SIMCONFIG_H #define DRAMSYSCONFIGURATION_SIMCONFIG_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include namespace DRAMSys::Config { -const std::string simConfigPath = "simconfig"; -enum class StoreMode +enum class StoreModeType { NoStorage, Store, @@ -52,34 +51,47 @@ enum class StoreMode Invalid = -1 }; -NLOHMANN_JSON_SERIALIZE_ENUM(StoreMode, {{StoreMode::Invalid, nullptr}, - {StoreMode::NoStorage, "NoStorage"}, - {StoreMode::Store, "Store"}, - {StoreMode::ErrorModel, "ErrorModel"}}) +NLOHMANN_JSON_SERIALIZE_ENUM(StoreModeType, {{StoreModeType::Invalid, nullptr}, + {StoreModeType::NoStorage, "NoStorage"}, + {StoreModeType::Store, "Store"}, + {StoreModeType::ErrorModel, "ErrorModel"}}) struct SimConfig { - std::optional addressOffset; - std::optional checkTLM2Protocol; - std::optional databaseRecording; - std::optional debug; - std::optional enableWindowing; - std::optional errorCsvFile; - std::optional errorChipSeed; - std::optional powerAnalysis; - std::optional simulationName; - std::optional simulationProgressBar; - std::optional storeMode; - std::optional thermalSimulation; - std::optional useMalloc; - std::optional windowSize; + static constexpr std::string_view KEY = "simconfig"; + static constexpr std::string_view SUB_DIR = "simconfig"; + + std::optional AddressOffset; + std::optional CheckTLM2Protocol; + std::optional DatabaseRecording; + std::optional Debug; + std::optional EnableWindowing; + std::optional ErrorCSVFile; + std::optional ErrorChipSeed; + std::optional PowerAnalysis; + std::optional SimulationName; + std::optional SimulationProgressBar; + std::optional StoreMode; + std::optional ThermalSimulation; + std::optional UseMalloc; + std::optional WindowSize; }; -void to_json(json_t &j, const SimConfig &c); -void from_json(const json_t &j, SimConfig &c); - -void from_dump(const std::string &dump, SimConfig &c); -std::string dump(const SimConfig &c, unsigned int indentation = -1); +NLOHMANN_JSONIFY_ALL_THINGS(SimConfig, + AddressOffset, + CheckTLM2Protocol, + DatabaseRecording, + Debug, + EnableWindowing, + ErrorCSVFile, + ErrorChipSeed, + PowerAnalysis, + SimulationName, + SimulationProgressBar, + StoreMode, + ThermalSimulation, + UseMalloc, + WindowSize) } // namespace Configuration diff --git a/src/configuration/DRAMSys/config/TraceSetup.cpp b/src/configuration/DRAMSys/config/TraceSetup.cpp deleted file mode 100644 index 9462c838..00000000 --- a/src/configuration/DRAMSys/config/TraceSetup.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2021, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Derek Christ - */ - -#include "TraceSetup.h" - -#include - -namespace DRAMSys::Config -{ - -TrafficInitiator::~TrafficInitiator() -{ -} - -TraceGeneratorState::~TraceGeneratorState() -{ -} - -void to_json(json_t &j, const TraceSetup &c) -{ - // Create an empty array - j = json_t::array(); - - for (const auto &initiator : c.initiators) - { - json_t initiator_j; - - std::visit( - [&initiator_j](auto &&initiator) - { - initiator_j["name"] = initiator.name; - initiator_j["clkMhz"] = initiator.clkMhz; - initiator_j["maxPendingReadRequests"] = initiator.maxPendingReadRequests; - initiator_j["maxPendingWriteRequests"] = initiator.maxPendingWriteRequests; - - using T = std::decay_t; - if constexpr (std::is_same_v) - { - initiator_j["type"] = "generator"; - initiator_j["seed"] = initiator.seed; - initiator_j["maxTransactions"] = initiator.maxTransactions; - initiator_j["idleUntil"] = initiator.idleUntil; - - // When there are less than 2 states, flatten out the json. - if (initiator.states.size() == 1) - { - std::visit( - [&initiator_j](auto &&state) - { - using U = std::decay_t; - - if constexpr (std::is_same_v) - { - initiator_j["numRequests"] = state.numRequests; - initiator_j["rwRatio"] = state.rwRatio; - initiator_j["addressDistribution"] = state.addressDistribution; - initiator_j["addressIncrement"] = state.addressIncrement; - initiator_j["minAddress"] = state.minAddress; - initiator_j["maxAddress"] = state.maxAddress; - initiator_j["clksPerRequest"] = state.clksPerRequest; - initiator_j["notify"] = state.notify; - } - else // if constexpr (std::is_same_v) - { - initiator_j["idleClks"] = state.idleClks; - } - }, - initiator.states.at(0)); - } - else - { - json_t states_j = json_t::array(); - - for (const auto &state : initiator.states) - { - json_t state_j; - state_j["id"] = state.first; - - std::visit( - [&state_j](auto &&state) - { - using U = std::decay_t; - - if constexpr (std::is_same_v) - { - state_j["numRequests"] = state.numRequests; - state_j["rwRatio"] = state.rwRatio; - state_j["addressDistribution"] = state.addressDistribution; - state_j["addressIncrement"] = state.addressIncrement; - state_j["minAddress"] = state.minAddress; - state_j["maxAddress"] = state.maxAddress; - state_j["clksPerRequest"] = state.clksPerRequest; - state_j["notify"] = state.notify; - } - else // if constexpr (std::is_same_v) - { - state_j["idleClks"] = state.idleClks; - } - }, - state.second); - - remove_null_values(state_j); - states_j.insert(states_j.end(), state_j); - } - initiator_j["states"] = states_j; - - json_t transitions_j = json_t::array(); - - for (const auto &transition : initiator.transitions) - { - json_t transition_j; - transition_j["from"] = transition.first; - transition_j["to"] = transition.second.to; - transition_j["probability"] = transition.second.probability; - remove_null_values(transition_j); - transitions_j.insert(transitions_j.end(), transition_j); - } - initiator_j["transitions"] = transitions_j; - } - } - else if constexpr (std::is_same_v) - { - initiator_j["type"] = "hammer"; - initiator_j["numRequests"] = initiator.numRequests; - initiator_j["rowIncrement"] = initiator.rowIncrement; - } - else // if constexpr (std::is_same_v) - { - initiator_j["type"] = "player"; - } - }, - initiator); - - remove_null_values(initiator_j); - j.insert(j.end(), initiator_j); - } -} - -void from_json(const json_t&j, TraceSetup &c) -{ - for (const auto &initiator_j : j) - { - // Default to Player, when not specified - TrafficInitiatorType type = initiator_j.value("type", TrafficInitiatorType::Player); - - std::variant initiator; - - if (type == TrafficInitiatorType::Player) - { - initiator = TracePlayer{}; - } - else if (type == TrafficInitiatorType::Generator) - { - TraceGenerator generator; - - auto process_state = [](const json_t&state_j) - -> std::pair> - { - std::variant state; - - if (state_j.contains("idleClks")) - { - // Idle state - TraceGeneratorIdleState idleState; - state_j.at("idleClks").get_to(idleState.idleClks); - - state = std::move(idleState); - } - else - { - // Traffic state - TraceGeneratorTrafficState trafficState; - state_j.at("numRequests").get_to(trafficState.numRequests); - state_j.at("rwRatio").get_to(trafficState.rwRatio); - state_j.at("addressDistribution").get_to(trafficState.addressDistribution); - - if (state_j.contains("addressIncrement")) - state_j.at("addressIncrement").get_to(trafficState.addressIncrement); - - if (state_j.contains("minAddress")) - state_j.at("minAddress").get_to(trafficState.minAddress); - - if (state_j.contains("maxAddress")) - state_j.at("maxAddress").get_to(trafficState.maxAddress); - - if (state_j.contains("clksPerRequest")) - state_j.at("clksPerRequest").get_to(trafficState.clksPerRequest); - - if (state_j.contains("notify")) - state_j.at("notify").get_to(trafficState.notify); - - state = std::move(trafficState); - } - - // Default to 0 - unsigned int id = 0; - - if (state_j.contains("id")) - id = state_j.at("id"); - - return {id, std::move(state)}; - }; - - if (initiator_j.contains("states")) - { - for (const auto &state_j : initiator_j.at("states")) - { - auto state = process_state(state_j); - generator.states[state.first] = std::move(state.second); - } - - for (const auto &transition_j : initiator_j.at("transitions")) - { - TraceGeneratorStateTransition transition; - unsigned int from = transition_j.at("from"); - transition.to = transition_j.at("to"); - transition.probability = transition_j.at("probability"); - generator.transitions.emplace(from, transition); - } - } - else // Only one state will be created - { - auto state = process_state(initiator_j); - generator.states[state.first] = std::move(state.second); - } - - if (initiator_j.contains("seed")) - initiator_j.at("seed").get_to(generator.seed); - - if (initiator_j.contains("maxTransactions")) - initiator_j.at("maxTransactions").get_to(generator.maxTransactions); - - if (initiator_j.contains("dataLength")) - initiator_j.at("dataLength").get_to(generator.dataLength); - - if (initiator_j.contains("idleUntil")) - initiator_j.at("idleUntil").get_to(generator.idleUntil); - - initiator = generator; - } - else if (type == TrafficInitiatorType::Hammer) - { - TraceHammer hammer; - - initiator_j.at("numRequests").get_to(hammer.numRequests); - initiator_j.at("rowIncrement").get_to(hammer.rowIncrement); - - initiator = hammer; - } - - std::visit( - [&initiator_j](auto &&initiator) - { - initiator_j.at("name").get_to(initiator.name); - initiator_j.at("clkMhz").get_to(initiator.clkMhz); - - if (initiator_j.contains("maxPendingReadRequests")) - initiator_j.at("maxPendingReadRequests").get_to(initiator.maxPendingReadRequests); - - if (initiator_j.contains("maxPendingWriteRequests")) - initiator_j.at("maxPendingWriteRequests").get_to(initiator.maxPendingWriteRequests); - }, - initiator); - - c.initiators.emplace_back(std::move(initiator)); - } -} - -void from_dump(const std::string &dump, TraceSetup &c) -{ - json_t json_tracesetup = json_t::parse(dump).at("tracesetup"); - json_tracesetup.get_to(c); -} - -std::string dump(const TraceSetup &c, unsigned int indentation) -{ - json_t json_tracesetup; - json_tracesetup["tracesetup"] = c; - return json_tracesetup.dump(indentation); -} - -} // namespace DRAMSys::Config diff --git a/src/configuration/DRAMSys/config/TraceSetup.h b/src/configuration/DRAMSys/config/TraceSetup.h index 3f14cbe1..1b67c82e 100644 --- a/src/configuration/DRAMSys/config/TraceSetup.h +++ b/src/configuration/DRAMSys/config/TraceSetup.h @@ -36,7 +36,7 @@ #ifndef DRAMSYSCONFIGURATION_TRACESETUP_H #define DRAMSYSCONFIGURATION_TRACESETUP_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include #include @@ -68,74 +68,141 @@ NLOHMANN_JSON_SERIALIZE_ENUM(AddressDistribution, {{AddressDistribution::Invalid {AddressDistribution::Random, "random"}, {AddressDistribution::Sequential, "sequential"}}) -struct TrafficInitiator +struct TracePlayer { - virtual ~TrafficInitiator() = 0; - uint64_t clkMhz; std::string name; std::optional maxPendingReadRequests; std::optional maxPendingWriteRequests; }; -struct TracePlayer : public TrafficInitiator -{ -}; +NLOHMANN_JSONIFY_ALL_THINGS( + TracePlayer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests) -struct TraceGeneratorState +struct TrafficGeneratorActiveState { - virtual ~TraceGeneratorState() = 0; -}; + unsigned int id; -struct TraceGeneratorTrafficState : public TraceGeneratorState -{ uint64_t numRequests; double rwRatio; AddressDistribution addressDistribution; std::optional addressIncrement; std::optional minAddress; std::optional maxAddress; - std::optional clksPerRequest; - std::optional notify; }; -struct TraceGeneratorIdleState : public TraceGeneratorState +NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorActiveState, + id, + numRequests, + rwRatio, + addressDistribution, + addressIncrement, + minAddress, + maxAddress) + +struct TrafficGeneratorIdleState { + unsigned int id; + uint64_t idleClks; }; -struct TraceGeneratorStateTransition +NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorIdleState, id, idleClks) + +struct TrafficGeneratorStateTransition { + unsigned int from; unsigned int to; float probability; }; -struct TraceGenerator : public TrafficInitiator +NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateTransition, from, to, probability) + +struct TrafficGenerator { + uint64_t clkMhz; + std::string name; + std::optional maxPendingReadRequests; + std::optional maxPendingWriteRequests; + std::optional seed; std::optional maxTransactions; std::optional dataLength; - std::map> states; - std::multimap transitions; - std::optional idleUntil; + std::optional dataAlignment; + + uint64_t numRequests; + double rwRatio; + AddressDistribution addressDistribution; + std::optional addressIncrement; + std::optional minAddress; + std::optional maxAddress; }; -struct TraceHammer : public TrafficInitiator +NLOHMANN_JSONIFY_ALL_THINGS(TrafficGenerator, + clkMhz, + name, + maxPendingReadRequests, + maxPendingWriteRequests, + seed, + maxTransactions, + dataLength, + dataAlignment, + numRequests, + rwRatio, + addressDistribution, + addressIncrement, + minAddress, + maxAddress) + +struct TrafficGeneratorStateMachine { + uint64_t clkMhz; + std::string name; + std::optional maxPendingReadRequests; + std::optional maxPendingWriteRequests; + + std::optional seed; + std::optional maxTransactions; + std::optional dataLength; + std::optional dataAlignment; + std::vector> states; + std::vector transitions; +}; + +NLOHMANN_JSONIFY_ALL_THINGS(TrafficGeneratorStateMachine, + clkMhz, + name, + maxPendingReadRequests, + maxPendingWriteRequests, + seed, + maxTransactions, + dataLength, + dataAlignment, + states, + transitions) + +struct RowHammer +{ + uint64_t clkMhz; + std::string name; + std::optional maxPendingReadRequests; + std::optional maxPendingWriteRequests; + uint64_t numRequests; uint64_t rowIncrement; }; -struct TraceSetup +NLOHMANN_JSONIFY_ALL_THINGS( + RowHammer, clkMhz, name, maxPendingReadRequests, maxPendingWriteRequests, numRequests, rowIncrement) + +struct TraceSetupConstants { - std::vector> initiators; + static constexpr std::string_view KEY = "tracesetup"; + static constexpr std::string_view SUB_DIR = "tracesetup"; }; -void to_json(json_t &j, const TraceSetup &c); -void from_json(const json_t &j, TraceSetup &c); - -void from_dump(const std::string &dump, TraceSetup &c); -std::string dump(const TraceSetup &c, unsigned int indentation = -1); +using TraceSetup = std::vector< + std::variant>; } // namespace Configuration diff --git a/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.cpp b/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.cpp index 977add14..6bc6527f 100644 --- a/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.cpp +++ b/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.cpp @@ -38,7 +38,7 @@ namespace DRAMSys::Config { -void to_json(json_t &j, const MemArchitectureSpec &c) +void to_json(json_t &j, const MemArchitectureSpecType &c) { j = json_t{}; @@ -48,7 +48,7 @@ void to_json(json_t &j, const MemArchitectureSpec &c) } } -void from_json(const json_t &j, MemArchitectureSpec &c) +void from_json(const json_t &j, MemArchitectureSpecType &c) { for (const auto &entry : j.items()) { diff --git a/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.h b/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.h index a03604ee..d3424cd8 100644 --- a/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.h +++ b/src/configuration/DRAMSys/config/memspec/MemArchitectureSpec.h @@ -36,20 +36,20 @@ #ifndef DRAMSYSCONFIGURATION_MEMARCHITECTURESPEC_H #define DRAMSYSCONFIGURATION_MEMARCHITECTURESPEC_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include namespace DRAMSys::Config { -struct MemArchitectureSpec +struct MemArchitectureSpecType { std::unordered_map entries; }; -void to_json(json_t &j, const MemArchitectureSpec &c); -void from_json(const json_t &j, MemArchitectureSpec &c); +void to_json(json_t &j, const MemArchitectureSpecType &c); +void from_json(const json_t &j, MemArchitectureSpecType &c); } // namespace Configuration diff --git a/src/configuration/DRAMSys/config/memspec/MemPowerSpec.h b/src/configuration/DRAMSys/config/memspec/MemPowerSpec.h index 1c85879f..4099bc90 100644 --- a/src/configuration/DRAMSys/config/memspec/MemPowerSpec.h +++ b/src/configuration/DRAMSys/config/memspec/MemPowerSpec.h @@ -36,7 +36,7 @@ #ifndef DRAMSYSCONFIGURATION_MEMPOWERSPEC_H #define DRAMSYSCONFIGURATION_MEMPOWERSPEC_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include diff --git a/src/configuration/DRAMSys/config/memspec/MemSpec.h b/src/configuration/DRAMSys/config/memspec/MemSpec.h index d20f0c03..adb00acf 100644 --- a/src/configuration/DRAMSys/config/memspec/MemSpec.h +++ b/src/configuration/DRAMSys/config/memspec/MemSpec.h @@ -36,7 +36,7 @@ #ifndef DRAMSYSCONFIGURATION_MEMSPEC_H #define DRAMSYSCONFIGURATION_MEMSPEC_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include "DRAMSys/config/memspec/MemArchitectureSpec.h" #include "DRAMSys/config/memspec/MemPowerSpec.h" #include "DRAMSys/config/memspec/MemTimingSpec.h" @@ -45,22 +45,20 @@ namespace DRAMSys::Config { -const std::string memSpecPath = "memspec"; - struct MemSpec { - MemArchitectureSpec memArchitectureSpec; + static constexpr std::string_view KEY = "memspec"; + static constexpr std::string_view SUB_DIR = "memspec"; + + MemArchitectureSpecType memarchitecturespec; std::string memoryId; std::string memoryType; - MemTimingSpec memTimingSpec; - std::optional memPowerSpec; + MemTimingSpecType memtimingspec; + std::optional mempowerspec; }; -void to_json(json &j, const MemSpec &c); -void from_json(const json &j, MemSpec &c); - -void from_dump(const std::string &dump, MemSpec &c); -std::string dump(const MemSpec &c, unsigned int indentation = -1); +NLOHMANN_JSONIFY_ALL_THINGS( + MemSpec, memarchitecturespec, memoryId, memoryType, memtimingspec, mempowerspec) } // namespace Configuration diff --git a/src/configuration/DRAMSys/config/memspec/MemTimingSpec.cpp b/src/configuration/DRAMSys/config/memspec/MemTimingSpec.cpp index f70e836d..af8b0eda 100644 --- a/src/configuration/DRAMSys/config/memspec/MemTimingSpec.cpp +++ b/src/configuration/DRAMSys/config/memspec/MemTimingSpec.cpp @@ -38,7 +38,7 @@ namespace DRAMSys::Config { -void to_json(json_t &j, const MemTimingSpec &c) +void to_json(json_t &j, const MemTimingSpecType &c) { j = json_t{}; @@ -48,7 +48,7 @@ void to_json(json_t &j, const MemTimingSpec &c) } } -void from_json(const json_t &j, MemTimingSpec &c) +void from_json(const json_t &j, MemTimingSpecType &c) { for (const auto &entry : j.items()) { diff --git a/src/configuration/DRAMSys/config/memspec/MemTimingSpec.h b/src/configuration/DRAMSys/config/memspec/MemTimingSpec.h index 239ac824..435f3e3a 100644 --- a/src/configuration/DRAMSys/config/memspec/MemTimingSpec.h +++ b/src/configuration/DRAMSys/config/memspec/MemTimingSpec.h @@ -36,7 +36,7 @@ #ifndef DRAMSYSCONFIGURATION_MEMTIMINGSPEC_H #define DRAMSYSCONFIGURATION_MEMTIMINGSPEC_H -#include "DRAMSys/config/ConfigUtil.h" +#include "DRAMSys/util/json.h" #include @@ -44,13 +44,13 @@ namespace DRAMSys::Config { using json = nlohmann::json; -struct MemTimingSpec +struct MemTimingSpecType { std::unordered_map entries; }; -void to_json(json &j, const MemTimingSpec &c); -void from_json(const json &j, MemTimingSpec &c); +void to_json(json &j, const MemTimingSpecType &c); +void from_json(const json &j, MemTimingSpecType &c); } // namespace Configuration diff --git a/src/libdramsys/DRAMSys/common/dramExtensions.h b/src/libdramsys/DRAMSys/common/dramExtensions.h index 7a8a80c1..b920747b 100644 --- a/src/libdramsys/DRAMSys/common/dramExtensions.h +++ b/src/libdramsys/DRAMSys/common/dramExtensions.h @@ -288,4 +288,18 @@ public: static bool notifyChildTransCompletion(tlm::tlm_generic_payload& trans); }; +class EccExtension : public tlm::tlm_extension +{ +public: + tlm_extension_base* clone() const override + { + return new EccExtension; + } + + void copy_from(tlm_extension_base const &ext) override + { + auto const &cpyFrom = static_cast(ext); + } +}; + #endif // DRAMEXTENSIONS_H diff --git a/src/libdramsys/DRAMSys/configuration/Configuration.cpp b/src/libdramsys/DRAMSys/configuration/Configuration.cpp index b3ae5fe4..1661e8ec 100644 --- a/src/libdramsys/DRAMSys/configuration/Configuration.cpp +++ b/src/libdramsys/DRAMSys/configuration/Configuration.cpp @@ -86,202 +86,232 @@ enum sc_time_unit string2TimeUnit(const std::string &s) } void Configuration::loadSimConfig(const DRAMSys::Config::SimConfig &simConfig) -{ - if (const auto& _addressOffset = simConfig.addressOffset) - addressOffset = *_addressOffset; +{ + addressOffset = simConfig.AddressOffset.value_or(addressOffset); + checkTLM2Protocol = simConfig.CheckTLM2Protocol.value_or(checkTLM2Protocol); + databaseRecording = simConfig.DatabaseRecording.value_or(databaseRecording); + debug = simConfig.Debug.value_or(debug); + enableWindowing = simConfig.EnableWindowing.value_or(enableWindowing); + simulationName = simConfig.SimulationName.value_or(simulationName); + simulationProgressBar = simConfig.SimulationProgressBar.value_or(simulationProgressBar); + useMalloc = simConfig.UseMalloc.value_or(useMalloc); - if (const auto& _checkTLM2Protocol = simConfig.checkTLM2Protocol) - checkTLM2Protocol = *_checkTLM2Protocol; - - if (const auto& _databaseRecording = simConfig.databaseRecording) - databaseRecording = *_databaseRecording; - - if (const auto& _debug = simConfig.debug) - debug = *_debug; - - if (const auto& _enableWindowing = simConfig.enableWindowing) - enableWindowing = *_enableWindowing; - - if (const auto& _powerAnalysis = simConfig.powerAnalysis) - { - powerAnalysis = *_powerAnalysis; -#ifndef DRAMPOWER - if (powerAnalysis) - SC_REPORT_FATAL("Configuration", "Power analysis is only supported with included DRAMPower library!"); -#endif - } - - if (const auto& _simulationName = simConfig.simulationName) - simulationName = *_simulationName; - - if (const auto& _simulationProgressBar = simConfig.simulationProgressBar) - simulationProgressBar = *_simulationProgressBar; - - if (const auto& _useMalloc = simConfig.useMalloc) - useMalloc = *_useMalloc; - - if (const auto& _windowSize = simConfig.windowSize) - windowSize = *_windowSize; + if (const auto &_storeMode = simConfig.StoreMode) + storeMode = [=] + { + switch (*_storeMode) + { + case DRAMSys::Config::StoreModeType::NoStorage: + return StoreMode::NoStorage; + case DRAMSys::Config::StoreModeType::Store: + return StoreMode::Store; + default: + SC_REPORT_FATAL("Configuration", "Invalid StoreMode"); + return StoreMode::NoStorage; // Silence Warning + } + }(); + windowSize = simConfig.WindowSize.value_or(windowSize); if (windowSize == 0) SC_REPORT_FATAL("Configuration", "Minimum window size is 1"); - if (const auto& _storeMode = simConfig.storeMode) - storeMode = [=] { - if (_storeMode == DRAMSys::Config::StoreMode::NoStorage) - return StoreMode::NoStorage; - else // (_storeMode == DRAMSys::Config::StoreMode::Store) - return StoreMode::Store; - }(); + powerAnalysis = simConfig.PowerAnalysis.value_or(powerAnalysis); +#ifndef DRAMPOWER + if (powerAnalysis) + SC_REPORT_FATAL("Configuration", "Power analysis is only supported with included DRAMPower library!"); +#endif } void Configuration::loadMCConfig(const DRAMSys::Config::McConfig &mcConfig) { - if (const auto& _pagePolicy = mcConfig.pagePolicy) - pagePolicy = [=] { - if (_pagePolicy == DRAMSys::Config::PagePolicy::Open) + if (const auto &_pagePolicy = mcConfig.PagePolicy) + pagePolicy = [=] + { + switch (*_pagePolicy) + { + case DRAMSys::Config::PagePolicyType::Open: return PagePolicy::Open; - else if (_pagePolicy == DRAMSys::Config::PagePolicy::OpenAdaptive) + case DRAMSys::Config::PagePolicyType::OpenAdaptive: return PagePolicy::OpenAdaptive; - else if (_pagePolicy == DRAMSys::Config::PagePolicy::Closed) + case DRAMSys::Config::PagePolicyType::Closed: return PagePolicy::Closed; - else + case DRAMSys::Config::PagePolicyType::ClosedAdaptive: return PagePolicy::ClosedAdaptive; + default: + SC_REPORT_FATAL("Configuration", "Invalid PagePolicy"); + return PagePolicy::Open; // Silence Warning + } }(); - if (const auto& _scheduler = mcConfig.scheduler) - scheduler = [=] { - if (_scheduler == DRAMSys::Config::Scheduler::Fifo) - return Scheduler::Fifo; - else if (_scheduler == DRAMSys::Config::Scheduler::FrFcfs) - return Scheduler::FrFcfs; - else if (_scheduler == DRAMSys::Config::Scheduler::FrFcfsGrp) - return Scheduler::FrFcfsGrp; - else if (_scheduler == DRAMSys::Config::Scheduler::GrpFrFcfs) - return Scheduler::GrpFrFcfs; - else - return Scheduler::GrpFrFcfsWm; + if (const auto &_scheduler = mcConfig.Scheduler) + scheduler = [=] + { + switch (*_scheduler) + { + case DRAMSys::Config::SchedulerType::Fifo: + return Scheduler::Fifo; + case DRAMSys::Config::SchedulerType::FrFcfs: + return Scheduler::FrFcfs; + case DRAMSys::Config::SchedulerType::FrFcfsGrp: + return Scheduler::FrFcfsGrp; + case DRAMSys::Config::SchedulerType::GrpFrFcfs: + return Scheduler::GrpFrFcfs; + case DRAMSys::Config::SchedulerType::GrpFrFcfsWm: + return Scheduler::GrpFrFcfsWm; + default: + SC_REPORT_FATAL("Configuration", "Invalid Scheduler"); + return Scheduler::Fifo; // Silence Warning + } }(); - if (const auto& _highWatermark = mcConfig.highWatermark) - highWatermark = *mcConfig.highWatermark; - - if (const auto& _lowWatermark = mcConfig.lowWatermark) - lowWatermark = *mcConfig.lowWatermark; - - if (const auto& _schedulerBuffer = mcConfig.schedulerBuffer) - schedulerBuffer = [=] { - if (_schedulerBuffer == DRAMSys::Config::SchedulerBuffer::Bankwise) + if (const auto &_schedulerBuffer = mcConfig.SchedulerBuffer) + schedulerBuffer = [=] + { + switch (*_schedulerBuffer) + { + case DRAMSys::Config::SchedulerBufferType::Bankwise: return SchedulerBuffer::Bankwise; - else if (_schedulerBuffer == DRAMSys::Config::SchedulerBuffer::ReadWrite) + case DRAMSys::Config::SchedulerBufferType::ReadWrite: return SchedulerBuffer::ReadWrite; - else + case DRAMSys::Config::SchedulerBufferType::Shared: return SchedulerBuffer::Shared; + default: + SC_REPORT_FATAL("Configuration", "Invalid SchedulerBuffer"); + return SchedulerBuffer::Bankwise; // Silence Warning + } }(); - if (const auto& _requestBufferSize = mcConfig.requestBufferSize) - requestBufferSize = *mcConfig.requestBufferSize; + if (const auto &_cmdMux = mcConfig.CmdMux) + cmdMux = [=] + { + switch (*_cmdMux) + { + case DRAMSys::Config::CmdMuxType::Oldest: + return CmdMux::Oldest; + case DRAMSys::Config::CmdMuxType::Strict: + return CmdMux::Strict; + default: + SC_REPORT_FATAL("Configuration", "Invalid CmdMux"); + return CmdMux::Oldest; // Silence Warning + } + }(); + if (const auto &_respQueue = mcConfig.RespQueue) + respQueue = [=] + { + switch (*_respQueue) + { + case DRAMSys::Config::RespQueueType::Fifo: + return RespQueue::Fifo; + case DRAMSys::Config::RespQueueType::Reorder: + return RespQueue::Reorder; + default: + SC_REPORT_FATAL("Configuration", "Invalid RespQueue"); + return RespQueue::Fifo; // Silence Warning + } + }(); + + if (const auto &_refreshPolicy = mcConfig.RefreshPolicy) + refreshPolicy = [=] + { + switch (*_refreshPolicy) + { + case DRAMSys::Config::RefreshPolicyType::NoRefresh: + return RefreshPolicy::NoRefresh; + case DRAMSys::Config::RefreshPolicyType::AllBank: + return RefreshPolicy::AllBank; + case DRAMSys::Config::RefreshPolicyType::PerBank: + return RefreshPolicy::PerBank; + case DRAMSys::Config::RefreshPolicyType::Per2Bank: + return RefreshPolicy::Per2Bank; + case DRAMSys::Config::RefreshPolicyType::SameBank: + return RefreshPolicy::SameBank; + default: + SC_REPORT_FATAL("Configuration", "Invalid RefreshPolicy"); + return RefreshPolicy::NoRefresh; // Silence Warning + } + }(); + + if (const auto &_powerDownPolicy = mcConfig.PowerDownPolicy) + powerDownPolicy = [=] + { + switch (*_powerDownPolicy) + { + case DRAMSys::Config::PowerDownPolicyType::NoPowerDown: + return PowerDownPolicy::NoPowerDown; + case DRAMSys::Config::PowerDownPolicyType::Staggered: + return PowerDownPolicy::Staggered; + default: + SC_REPORT_FATAL("Configuration", "Invalid PowerDownPolicy"); + return PowerDownPolicy::NoPowerDown; // Silence Warning + } + }(); + + if (const auto &_arbiter = mcConfig.Arbiter) + arbiter = [=] + { + switch (*_arbiter) + { + case DRAMSys::Config::ArbiterType::Simple: + return Arbiter::Simple; + case DRAMSys::Config::ArbiterType::Fifo: + return Arbiter::Fifo; + case DRAMSys::Config::ArbiterType::Reorder: + return Arbiter::Reorder; + default: + SC_REPORT_FATAL("Configuration", "Invalid Arbiter"); + return Arbiter::Simple; // Silence Warning + } + }(); + + refreshMaxPostponed = mcConfig.RefreshMaxPostponed.value_or(refreshMaxPostponed); + refreshMaxPulledin = mcConfig.RefreshMaxPulledin.value_or(refreshMaxPulledin); + highWatermark = mcConfig.HighWatermark.value_or(highWatermark); + lowWatermark = mcConfig.LowWatermark.value_or(lowWatermark); + maxActiveTransactions = mcConfig.MaxActiveTransactions.value_or(maxActiveTransactions); + refreshManagement = mcConfig.RefreshManagement.value_or(refreshManagement); + + requestBufferSize = mcConfig.RequestBufferSize.value_or(requestBufferSize); if (requestBufferSize == 0) SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!"); - if (const auto& _cmdMux = mcConfig.cmdMux) - cmdMux = [=] { - if (_cmdMux == DRAMSys::Config::CmdMux::Oldest) - return CmdMux::Oldest; - else - return CmdMux::Strict; - }(); - - if (const auto& _respQueue = mcConfig.respQueue) - respQueue = [=] { - if (_respQueue == DRAMSys::Config::RespQueue::Fifo) - return RespQueue::Fifo; - else - return RespQueue::Reorder; - }(); - - if (const auto& _refreshPolicy = mcConfig.refreshPolicy) - refreshPolicy = [=] { - if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::NoRefresh) - return RefreshPolicy::NoRefresh; - else if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::AllBank) - return RefreshPolicy::AllBank; - else if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::PerBank) - return RefreshPolicy::PerBank; - else if (_refreshPolicy == DRAMSys::Config::RefreshPolicy::Per2Bank) - return RefreshPolicy::Per2Bank; - else // if (policy == DRAMSys::Config::RefreshPolicy::SameBank) - return RefreshPolicy::SameBank; - }(); - - if (const auto& _refreshMaxPostponed = mcConfig.refreshMaxPostponed) - refreshMaxPostponed = *_refreshMaxPostponed; - - if (const auto& _refreshMaxPulledin = mcConfig.refreshMaxPulledin) - refreshMaxPulledin = *_refreshMaxPulledin; - - if (const auto& _powerDownPolicy = mcConfig.powerDownPolicy) - powerDownPolicy = [=] { - if (_powerDownPolicy == DRAMSys::Config::PowerDownPolicy::NoPowerDown) - return PowerDownPolicy::NoPowerDown; - else - return PowerDownPolicy::Staggered; - }(); - - if (const auto& _arbiter = mcConfig.arbiter) - arbiter = [=] { - if (_arbiter == DRAMSys::Config::Arbiter::Simple) - return Arbiter::Simple; - else if (_arbiter == DRAMSys::Config::Arbiter::Fifo) - return Arbiter::Fifo; - else - return Arbiter::Reorder; - }(); - - if (const auto& _maxActiveTransactions = mcConfig.maxActiveTransactions) - maxActiveTransactions = *_maxActiveTransactions; - - if (const auto& _refreshManagement = mcConfig.refreshManagement) - refreshManagement = *_refreshManagement; - - if (const auto& _arbitrationDelayFw = mcConfig.arbitrationDelayFw) + if (const auto& _arbitrationDelayFw = mcConfig.ArbitrationDelayFw) { arbitrationDelayFw = std::round(sc_time(*_arbitrationDelayFw, SC_NS) / memSpec->tCK) * memSpec->tCK; } - if (const auto& _arbitrationDelayBw = mcConfig.arbitrationDelayBw) + if (const auto& _arbitrationDelayBw = mcConfig.ArbitrationDelayBw) { arbitrationDelayBw = std::round(sc_time(*_arbitrationDelayBw, SC_NS) / memSpec->tCK) * memSpec->tCK; } - if (const auto& _thinkDelayFw = mcConfig.thinkDelayFw) + if (const auto& _thinkDelayFw = mcConfig.ThinkDelayFw) { thinkDelayFw = std::round(sc_time(*_thinkDelayFw, SC_NS) / memSpec->tCK) * memSpec->tCK; } - if (const auto& _thinkDelayBw = mcConfig.thinkDelayBw) + if (const auto& _thinkDelayBw = mcConfig.ThinkDelayBw) { thinkDelayBw = std::round(sc_time(*_thinkDelayBw, SC_NS) / memSpec->tCK) * memSpec->tCK; } - if (const auto& _phyDelayFw = mcConfig.phyDelayFw) + if (const auto& _phyDelayFw = mcConfig.PhyDelayFw) { phyDelayFw = std::round(sc_time(*_phyDelayFw, SC_NS) / memSpec->tCK) * memSpec->tCK; } - if (const auto& _phyDelayBw = mcConfig.phyDelayBw) + if (const auto& _phyDelayBw = mcConfig.PhyDelayBw) { phyDelayBw = std::round(sc_time(*_phyDelayBw, SC_NS) / memSpec->tCK) * memSpec->tCK; } { - auto _blockingReadDelay = mcConfig.blockingReadDelay.value_or(60); + auto _blockingReadDelay = mcConfig.BlockingReadDelay.value_or(60); blockingReadDelay = std::round(sc_time(_blockingReadDelay, SC_NS) / memSpec->tCK) * memSpec->tCK; } { - auto _blockingWriteDelay = mcConfig.blockingWriteDelay.value_or(60); + auto _blockingWriteDelay = mcConfig.BlockingWriteDelay.value_or(60); blockingWriteDelay = std::round(sc_time(_blockingWriteDelay, SC_NS) / memSpec->tCK) * memSpec->tCK; } } diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpec.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpec.cpp index 6d25dac1..e27e22d1 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpec.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpec.cpp @@ -55,20 +55,20 @@ MemSpec::MemSpec(const DRAMSys::Config::MemSpec& memSpec, banksPerChannel(banksPerChannel), bankGroupsPerChannel(bankGroupsPerChannel), devicesPerRank(devicesPerRank), - rowsPerBank(memSpec.memArchitectureSpec.entries.at("nbrOfRows")), - columnsPerRow(memSpec.memArchitectureSpec.entries.at("nbrOfColumns")), - defaultBurstLength(memSpec.memArchitectureSpec.entries.at("burstLength")), - maxBurstLength(memSpec.memArchitectureSpec.entries.find("maxBurstLength") != - memSpec.memArchitectureSpec.entries.end() - ? memSpec.memArchitectureSpec.entries.at("maxBurstLength") + rowsPerBank(memSpec.memarchitecturespec.entries.at("nbrOfRows")), + columnsPerRow(memSpec.memarchitecturespec.entries.at("nbrOfColumns")), + defaultBurstLength(memSpec.memarchitecturespec.entries.at("burstLength")), + maxBurstLength(memSpec.memarchitecturespec.entries.find("maxBurstLength") != + memSpec.memarchitecturespec.entries.end() + ? memSpec.memarchitecturespec.entries.at("maxBurstLength") : defaultBurstLength), - dataRate(memSpec.memArchitectureSpec.entries.at("dataRate")), - bitWidth(memSpec.memArchitectureSpec.entries.at("width")), + dataRate(memSpec.memarchitecturespec.entries.at("dataRate")), + bitWidth(memSpec.memarchitecturespec.entries.at("width")), dataBusWidth(bitWidth* devicesPerRank), bytesPerBeat(dataBusWidth / 8), defaultBytesPerBurst((defaultBurstLength* dataBusWidth) / 8), maxBytesPerBurst((maxBurstLength* dataBusWidth) / 8), - fCKMHz(memSpec.memTimingSpec.entries.at("clkMhz")), + fCKMHz(memSpec.memtimingspec.entries.at("clkMhz")), tCK(sc_time(1.0 / fCKMHz, SC_US)), memoryId(memSpec.memoryId), memoryType(memoryType), diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR3.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR3.cpp index 9271fdf5..719b3ba8 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR3.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR3.cpp @@ -45,61 +45,61 @@ using namespace tlm; MemSpecDDR3::MemSpecDDR3(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::DDR3, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), tPD (tCKE), - tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")), - tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")), - tAL (tCK * memSpec.memTimingSpec.entries.at("AL")), - tXPDLL (tCK * memSpec.memTimingSpec.entries.at("XPDLL")), - tXSDLL (tCK * memSpec.memTimingSpec.entries.at("XSDLL")), - tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")), - tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")), - tREFPDEN (tCK * memSpec.memTimingSpec.entries.at("REFPDEN")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")), - iDD0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd0") : 0), - iDD2N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n") : 0), - iDD3N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n") : 0), - iDD4R (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r") : 0), - iDD4W (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w") : 0), - iDD5 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd5") : 0), - iDD6 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd6") : 0), - vDD (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd") : 0), - iDD2P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p0") : 0), - iDD2P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p1") : 0), - iDD3P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p0") : 0), - iDD3P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p1") : 0) + tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")), + tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")), + tAL (tCK * memSpec.memtimingspec.entries.at("AL")), + tXPDLL (tCK * memSpec.memtimingspec.entries.at("XPDLL")), + tXSDLL (tCK * memSpec.memtimingspec.entries.at("XSDLL")), + tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")), + tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")), + tREFPDEN (tCK * memSpec.memtimingspec.entries.at("REFPDEN")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")), + iDD0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd0") : 0), + iDD2N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n") : 0), + iDD3N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n") : 0), + iDD4R (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r") : 0), + iDD4W (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w") : 0), + iDD5 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd5") : 0), + iDD6 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd6") : 0), + vDD (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd") : 0), + iDD2P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p0") : 0), + iDD2P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p1") : 0), + iDD3P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p0") : 0), + iDD3P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p1") : 0) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; memorySizeBytes = deviceSizeBytes * devicesPerRank * ranksPerChannel * numberOfChannels; - if (!memSpec.memPowerSpec.has_value()) + if (!memSpec.mempowerspec.has_value()) SC_REPORT_FATAL("MemSpec", "No power spec defined!"); std::cout << headline << std::endl; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR4.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR4.cpp index 594cda9b..89be15b6 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR4.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecDDR4.cpp @@ -45,79 +45,79 @@ using namespace tlm; MemSpecDDR4::MemSpecDDR4(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::DDR4, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), tPD (tCKE), - tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tRPRE (tCK * memSpec.memTimingSpec.entries.at("RPRE")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWPRE (tCK * memSpec.memTimingSpec.entries.at("WPRE")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tREFI ((memSpec.memTimingSpec.entries.at("REFM") == 4) ? - (tCK * (static_cast(memSpec.memTimingSpec.entries.at("REFI")) / 4)) : - ((memSpec.memTimingSpec.entries.at("REFM") == 2) ? - (tCK * (static_cast(memSpec.memTimingSpec.entries.at("REFI")) / 2)) : - (tCK * memSpec.memTimingSpec.entries.at("REFI")))), - tRFC ((memSpec.memTimingSpec.entries.at("REFM") == 4) ? - (tCK * memSpec.memTimingSpec.entries.at("RFC4")) : - ((memSpec.memTimingSpec.entries.at("REFM") == 2) ? - (tCK * memSpec.memTimingSpec.entries.at("RFC2")) : - (tCK * memSpec.memTimingSpec.entries.at("RFC")))), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tCCD_S (tCK * memSpec.memTimingSpec.entries.at("CCD_S")), - tCCD_L (tCK * memSpec.memTimingSpec.entries.at("CCD_L")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tRRD_S (tCK * memSpec.memTimingSpec.entries.at("RRD_S")), - tRRD_L (tCK * memSpec.memTimingSpec.entries.at("RRD_L")), - tWTR_S (tCK * memSpec.memTimingSpec.entries.at("WTR_S")), - tWTR_L (tCK * memSpec.memTimingSpec.entries.at("WTR_L")), - tAL (tCK * memSpec.memTimingSpec.entries.at("AL")), - tXPDLL (tCK * memSpec.memTimingSpec.entries.at("XPDLL")), - tXSDLL (tCK * memSpec.memTimingSpec.entries.at("XSDLL")), - tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")), - tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")), - tREFPDEN (tCK * memSpec.memTimingSpec.entries.at("REFPDEN")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")), - iDD0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd0") : 0), - iDD2N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n") : 0), - iDD3N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n") : 0), - iDD4R (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r") : 0), - iDD4W (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w") : 0), - iDD5 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd5") : 0), - iDD6 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd6") : 0), - vDD (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd") : 0), - iDD02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd02") : 0), - iDD2P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p0") : 0), - iDD2P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p1") : 0), - iDD3P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p0") : 0), - iDD3P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p1") : 0), - iDD62 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd62") : 0), - vDD2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd2") : 0) + tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tRPRE (tCK * memSpec.memtimingspec.entries.at("RPRE")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWPRE (tCK * memSpec.memtimingspec.entries.at("WPRE")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tREFI ((memSpec.memtimingspec.entries.at("REFM") == 4) ? + (tCK * (static_cast(memSpec.memtimingspec.entries.at("REFI")) / 4)) : + ((memSpec.memtimingspec.entries.at("REFM") == 2) ? + (tCK * (static_cast(memSpec.memtimingspec.entries.at("REFI")) / 2)) : + (tCK * memSpec.memtimingspec.entries.at("REFI")))), + tRFC ((memSpec.memtimingspec.entries.at("REFM") == 4) ? + (tCK * memSpec.memtimingspec.entries.at("RFC4")) : + ((memSpec.memtimingspec.entries.at("REFM") == 2) ? + (tCK * memSpec.memtimingspec.entries.at("RFC2")) : + (tCK * memSpec.memtimingspec.entries.at("RFC")))), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tCCD_S (tCK * memSpec.memtimingspec.entries.at("CCD_S")), + tCCD_L (tCK * memSpec.memtimingspec.entries.at("CCD_L")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tRRD_S (tCK * memSpec.memtimingspec.entries.at("RRD_S")), + tRRD_L (tCK * memSpec.memtimingspec.entries.at("RRD_L")), + tWTR_S (tCK * memSpec.memtimingspec.entries.at("WTR_S")), + tWTR_L (tCK * memSpec.memtimingspec.entries.at("WTR_L")), + tAL (tCK * memSpec.memtimingspec.entries.at("AL")), + tXPDLL (tCK * memSpec.memtimingspec.entries.at("XPDLL")), + tXSDLL (tCK * memSpec.memtimingspec.entries.at("XSDLL")), + tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")), + tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")), + tREFPDEN (tCK * memSpec.memtimingspec.entries.at("REFPDEN")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")), + iDD0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd0") : 0), + iDD2N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n") : 0), + iDD3N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n") : 0), + iDD4R (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r") : 0), + iDD4W (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w") : 0), + iDD5 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd5") : 0), + iDD6 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd6") : 0), + vDD (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd") : 0), + iDD02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd02") : 0), + iDD2P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p0") : 0), + iDD2P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p1") : 0), + iDD3P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p0") : 0), + iDD3P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p1") : 0), + iDD62 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd62") : 0), + vDD2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd2") : 0) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; memorySizeBytes = deviceSizeBytes * devicesPerRank * ranksPerChannel * numberOfChannels; - if (!memSpec.memPowerSpec.has_value()) + if (!memSpec.mempowerspec.has_value()) SC_REPORT_WARNING("MemSpec", "No power spec defined!"); std::cout << headline << std::endl; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5.cpp index 976f5ae1..10f59aac 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5.cpp @@ -45,52 +45,52 @@ using namespace tlm; MemSpecGDDR5::MemSpecGDDR5(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::GDDR5, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")), - tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")), - tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")), - tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")), - tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")), - tCL (tCK * memSpec.memTimingSpec.entries.at("CL")), - tWCK2CKPIN (tCK * memSpec.memTimingSpec.entries.at("WCK2CKPIN")), - tWCK2CK (tCK * memSpec.memTimingSpec.entries.at("WCK2CK")), - tWCK2DQO (tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")), - tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWCK2DQI (tCK * memSpec.memTimingSpec.entries.at("WCK2DQI")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")), - tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), - tPD (tCK * memSpec.memTimingSpec.entries.at("PD")), - tXPN (tCK * memSpec.memTimingSpec.entries.at("XPN")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")), - tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), - tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")), - tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - t32AW (tCK * memSpec.memTimingSpec.entries.at("32AW")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")), - tLK (tCK * memSpec.memTimingSpec.entries.at("LK")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")) + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")), + tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")), + tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")), + tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")), + tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")), + tCL (tCK * memSpec.memtimingspec.entries.at("CL")), + tWCK2CKPIN (tCK * memSpec.memtimingspec.entries.at("WCK2CKPIN")), + tWCK2CK (tCK * memSpec.memtimingspec.entries.at("WCK2CK")), + tWCK2DQO (tCK * memSpec.memtimingspec.entries.at("WCK2DQO")), + tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWCK2DQI (tCK * memSpec.memtimingspec.entries.at("WCK2DQI")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")), + tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), + tPD (tCK * memSpec.memtimingspec.entries.at("PD")), + tXPN (tCK * memSpec.memtimingspec.entries.at("XPN")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFIPB (tCK * memSpec.memtimingspec.entries.at("REFIPB")), + tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")), + tRFCPB (tCK * memSpec.memtimingspec.entries.at("RFCPB")), + tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")), + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + t32AW (tCK * memSpec.memtimingspec.entries.at("32AW")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")), + tLK (tCK * memSpec.memtimingspec.entries.at("LK")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5X.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5X.cpp index 7b4cf66e..d1e86148 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5X.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR5X.cpp @@ -45,52 +45,52 @@ using namespace tlm; MemSpecGDDR5X::MemSpecGDDR5X(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::GDDR5X, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")), - tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")), - tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")), - tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")), - tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")), - tRL (tCK * memSpec.memTimingSpec.entries.at("CL")), - tWCK2CKPIN (tCK * memSpec.memTimingSpec.entries.at("WCK2CKPIN")), - tWCK2CK (tCK * memSpec.memTimingSpec.entries.at("WCK2CK")), - tWCK2DQO (tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")), - tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWCK2DQI (tCK * memSpec.memTimingSpec.entries.at("WCK2DQI")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")), - tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), - tPD (tCK * memSpec.memTimingSpec.entries.at("PD")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")), - tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), - tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")), - tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - t32AW (tCK * memSpec.memTimingSpec.entries.at("32AW")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")), - tLK (tCK * memSpec.memTimingSpec.entries.at("LK")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("TRS")) + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")), + tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")), + tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")), + tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")), + tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")), + tRL (tCK * memSpec.memtimingspec.entries.at("CL")), + tWCK2CKPIN (tCK * memSpec.memtimingspec.entries.at("WCK2CKPIN")), + tWCK2CK (tCK * memSpec.memtimingspec.entries.at("WCK2CK")), + tWCK2DQO (tCK * memSpec.memtimingspec.entries.at("WCK2DQO")), + tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWCK2DQI (tCK * memSpec.memtimingspec.entries.at("WCK2DQI")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")), + tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), + tPD (tCK * memSpec.memtimingspec.entries.at("PD")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFIPB (tCK * memSpec.memtimingspec.entries.at("REFIPB")), + tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")), + tRFCPB (tCK * memSpec.memtimingspec.entries.at("RFCPB")), + tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")), + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + t32AW (tCK * memSpec.memtimingspec.entries.at("32AW")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")), + tLK (tCK * memSpec.memtimingspec.entries.at("LK")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("TRS")) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR6.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR6.cpp index 64b78b14..127f331e 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR6.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecGDDR6.cpp @@ -45,55 +45,55 @@ using namespace tlm; MemSpecGDDR6::MemSpecGDDR6(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::GDDR6, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at( "nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at( "nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at( "nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - per2BankOffset(memSpec.memArchitectureSpec.entries.at("per2BankOffset")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")), - tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")), - tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")), - tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")), - tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tWCK2CKPIN (tCK * memSpec.memTimingSpec.entries.at("WCK2CKPIN")), - tWCK2CK (tCK * memSpec.memTimingSpec.entries.at("WCK2CK")), - tWCK2DQO (tCK * memSpec.memTimingSpec.entries.at("WCK2DQO")), - tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWCK2DQI (tCK * memSpec.memTimingSpec.entries.at("WCK2DQI")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")), - tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")), - tPD (tCK * memSpec.memTimingSpec.entries.at("PD")), - tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFIpb (tCK * memSpec.memTimingSpec.entries.at("REFIpb")), - tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCab")), - tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCpb")), - tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")), - tLK (tCK * memSpec.memTimingSpec.entries.at("LK")), - tACTPDE (tCK * memSpec.memTimingSpec.entries.at("ACTPDE")), - tPREPDE (tCK * memSpec.memTimingSpec.entries.at("PREPDE")), - tREFPDE (tCK * memSpec.memTimingSpec.entries.at("REFPDE")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")) + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at( "nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at( "nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at( "nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + per2BankOffset(memSpec.memarchitecturespec.entries.at("per2BankOffset")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")), + tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")), + tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")), + tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")), + tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tWCK2CKPIN (tCK * memSpec.memtimingspec.entries.at("WCK2CKPIN")), + tWCK2CK (tCK * memSpec.memtimingspec.entries.at("WCK2CK")), + tWCK2DQO (tCK * memSpec.memtimingspec.entries.at("WCK2DQO")), + tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWCK2DQI (tCK * memSpec.memtimingspec.entries.at("WCK2DQI")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")), + tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")), + tPD (tCK * memSpec.memtimingspec.entries.at("PD")), + tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFIpb (tCK * memSpec.memtimingspec.entries.at("REFIpb")), + tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCab")), + tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCpb")), + tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")), + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")), + tLK (tCK * memSpec.memtimingspec.entries.at("LK")), + tACTPDE (tCK * memSpec.memtimingspec.entries.at("ACTPDE")), + tPREPDE (tCK * memSpec.memtimingspec.entries.at("PREPDE")), + tREFPDE (tCK * memSpec.memtimingspec.entries.at("REFPDE")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecHBM2.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecHBM2.cpp index 479a9069..d3aa9e1f 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecHBM2.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecHBM2.cpp @@ -45,47 +45,47 @@ using namespace tlm; MemSpecHBM2::MemSpecHBM2(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::HBM2, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") - * memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")), - tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")), - tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")), - tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tPL (tCK * memSpec.memTimingSpec.entries.at("PL")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")), - tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")), - tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")), - tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")), - tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + / memSpec.memarchitecturespec.entries.at("nbrOfBankGroups"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfBankGroups") + * memSpec.memarchitecturespec.entries.at("nbrOfPseudoChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRCDRD (tCK * memSpec.memtimingspec.entries.at("RCDRD")), + tRCDWR (tCK * memSpec.memtimingspec.entries.at("RCDWR")), + tRRDL (tCK * memSpec.memtimingspec.entries.at("RRDL")), + tRRDS (tCK * memSpec.memtimingspec.entries.at("RRDS")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tPL (tCK * memSpec.memtimingspec.entries.at("PL")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tCCDL (tCK * memSpec.memtimingspec.entries.at("CCDL")), + tCCDS (tCK * memSpec.memtimingspec.entries.at("CCDS")), + tWTRL (tCK * memSpec.memtimingspec.entries.at("WTRL")), + tWTRS (tCK * memSpec.memtimingspec.entries.at("WTRS")), + tRTW (tCK * memSpec.memtimingspec.entries.at("RTW")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), tPD (tCKE), tCKESR (tCKE + tCK), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), - tRFCSB (tCK * memSpec.memTimingSpec.entries.at("RFCSB")), - tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFISB (tCK * memSpec.memTimingSpec.entries.at("REFISB")) + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")), + tRFCSB (tCK * memSpec.memtimingspec.entries.at("RFCSB")), + tRREFD (tCK * memSpec.memtimingspec.entries.at("RREFD")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFISB (tCK * memSpec.memtimingspec.entries.at("REFISB")) { commandLengthInCycles[Command::ACT] = 2; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecLPDDR4.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecLPDDR4.cpp index 0c8b80ea..3f72958e 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecLPDDR4.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecLPDDR4.cpp @@ -45,47 +45,47 @@ using namespace tlm; MemSpecLPDDR4::MemSpecLPDDR4(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::LPDDR4, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tREFIpb (tCK * memSpec.memTimingSpec.entries.at("REFIPB")), - tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCAB")), - tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCPB")), - tRPab (tCK * memSpec.memTimingSpec.entries.at("RPAB")), - tRPpb (tCK * memSpec.memTimingSpec.entries.at("RPPB")), - tRCab (tCK * memSpec.memTimingSpec.entries.at("RCAB")), - tRCpb (tCK * memSpec.memTimingSpec.entries.at("RCPB")), - tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")), - tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tRPST (tCK * memSpec.memTimingSpec.entries.at("RPST")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tDQSS (tCK * memSpec.memTimingSpec.entries.at("DQSS")), - tDQS2DQ (tCK * memSpec.memTimingSpec.entries.at("DQS2DQ")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tWPRE (tCK * memSpec.memTimingSpec.entries.at("WPRE")), - tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tSR (tCK * memSpec.memTimingSpec.entries.at("SR")), - tXSR (tCK * memSpec.memTimingSpec.entries.at("XSR")), - tESCKE (tCK * memSpec.memTimingSpec.entries.at("ESCKE")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), - tCMDCKE (tCK * memSpec.memTimingSpec.entries.at("CMDCKE")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")) + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tREFIpb (tCK * memSpec.memtimingspec.entries.at("REFIPB")), + tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCAB")), + tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCPB")), + tRPab (tCK * memSpec.memtimingspec.entries.at("RPAB")), + tRPpb (tCK * memSpec.memtimingspec.entries.at("RPPB")), + tRCab (tCK * memSpec.memtimingspec.entries.at("RCAB")), + tRCpb (tCK * memSpec.memtimingspec.entries.at("RCPB")), + tPPD (tCK * memSpec.memtimingspec.entries.at("PPD")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")), + tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tRPST (tCK * memSpec.memtimingspec.entries.at("RPST")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tDQSS (tCK * memSpec.memtimingspec.entries.at("DQSS")), + tDQS2DQ (tCK * memSpec.memtimingspec.entries.at("DQS2DQ")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tWPRE (tCK * memSpec.memtimingspec.entries.at("WPRE")), + tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tSR (tCK * memSpec.memtimingspec.entries.at("SR")), + tXSR (tCK * memSpec.memtimingspec.entries.at("XSR")), + tESCKE (tCK * memSpec.memtimingspec.entries.at("ESCKE")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), + tCMDCKE (tCK * memSpec.memtimingspec.entries.at("CMDCKE")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")) { commandLengthInCycles[Command::ACT] = 4; commandLengthInCycles[Command::PREPB] = 2; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecSTTMRAM.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecSTTMRAM.cpp index b68f15f0..a46bbdbe 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecSTTMRAM.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecSTTMRAM.cpp @@ -45,40 +45,40 @@ using namespace tlm; MemSpecSTTMRAM::MemSpecSTTMRAM(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::STTMRAM, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), tPD (tCKE), - tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), - tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")), - tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")), - tAL (tCK * memSpec.memTimingSpec.entries.at("AL")), - tXPDLL (tCK * memSpec.memTimingSpec.entries.at("XPDLL")), - tXSDLL (tCK * memSpec.memTimingSpec.entries.at("XSDLL")), - tACTPDEN (tCK * memSpec.memTimingSpec.entries.at("ACTPDEN")), - tPRPDEN (tCK * memSpec.memTimingSpec.entries.at("PRPDEN")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")) + tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tXS (tCK * memSpec.memtimingspec.entries.at("XS")), + tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")), + tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")), + tAL (tCK * memSpec.memtimingspec.entries.at("AL")), + tXPDLL (tCK * memSpec.memtimingspec.entries.at("XPDLL")), + tXSDLL (tCK * memSpec.memtimingspec.entries.at("XSDLL")), + tACTPDEN (tCK * memSpec.memtimingspec.entries.at("ACTPDEN")), + tPRPDEN (tCK * memSpec.memtimingspec.entries.at("PRPDEN")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO.cpp index a47a3e77..9092122f 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO.cpp @@ -45,67 +45,67 @@ using namespace tlm; MemSpecWideIO::MemSpecWideIO(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::WideIO, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), - tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tAC (tCK * memSpec.memTimingSpec.entries.at("AC")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tXSR (tCK * memSpec.memTimingSpec.entries.at("XSR")), - tCCD_R (tCK * memSpec.memTimingSpec.entries.at("CCD_R")), - tCCD_W (tCK * memSpec.memTimingSpec.entries.at("CCD_W")), - tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), - tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), - tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), - tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")), - tTAW (tCK * memSpec.memTimingSpec.entries.at("TAW")), - tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")), - iDD0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd0") : 0), - iDD2N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n") : 0), - iDD3N (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n") : 0), - iDD4R (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r") : 0), - iDD4W (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w") : 0), - iDD5 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd5") : 0), - iDD6 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd6") : 0), - vDD (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd") : 0), - iDD02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd02") : 0), - iDD2P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p0") : 0), - iDD2P02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p02") : 0), - iDD2P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p1") : 0), - iDD2P12 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2p12") : 0), - iDD2N2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd2n2") : 0), - iDD3P0 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p0") : 0), - iDD3P02 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p02") : 0), - iDD3P1 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p1") : 0), - iDD3P12 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3p12") : 0), - iDD3N2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd3n2") : 0), - iDD4R2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4r2") : 0), - iDD4W2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd4w2") : 0), - iDD52 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd52") : 0), - iDD62 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("idd62") : 0), - vDD2 (memSpec.memPowerSpec.has_value() ? memSpec.memPowerSpec.value().entries.at("vdd2") : 0) + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), + tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tAC (tCK * memSpec.memtimingspec.entries.at("AC")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tRC (tCK * memSpec.memtimingspec.entries.at("RC")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tXSR (tCK * memSpec.memtimingspec.entries.at("XSR")), + tCCD_R (tCK * memSpec.memtimingspec.entries.at("CCD_R")), + tCCD_W (tCK * memSpec.memtimingspec.entries.at("CCD_W")), + tREFI (tCK * memSpec.memtimingspec.entries.at("REFI")), + tRFC (tCK * memSpec.memtimingspec.entries.at("RFC")), + tRP (tCK * memSpec.memtimingspec.entries.at("RP")), + tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")), + tTAW (tCK * memSpec.memtimingspec.entries.at("TAW")), + tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")), + iDD0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd0") : 0), + iDD2N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n") : 0), + iDD3N (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n") : 0), + iDD4R (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r") : 0), + iDD4W (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w") : 0), + iDD5 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd5") : 0), + iDD6 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd6") : 0), + vDD (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd") : 0), + iDD02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd02") : 0), + iDD2P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p0") : 0), + iDD2P02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p02") : 0), + iDD2P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p1") : 0), + iDD2P12 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2p12") : 0), + iDD2N2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd2n2") : 0), + iDD3P0 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p0") : 0), + iDD3P02 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p02") : 0), + iDD3P1 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p1") : 0), + iDD3P12 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3p12") : 0), + iDD3N2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd3n2") : 0), + iDD4R2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4r2") : 0), + iDD4W2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd4w2") : 0), + iDD52 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd52") : 0), + iDD62 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("idd62") : 0), + vDD2 (memSpec.mempowerspec.has_value() ? memSpec.mempowerspec.value().entries.at("vdd2") : 0) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; memorySizeBytes = deviceSizeBytes * ranksPerChannel * numberOfChannels; - if (!memSpec.memPowerSpec.has_value()) + if (!memSpec.mempowerspec.has_value()) SC_REPORT_FATAL("MemSpec", "No power spec defined!"); std::cout << headline << std::endl; diff --git a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO2.cpp b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO2.cpp index 2cb5a443..81462f78 100644 --- a/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO2.cpp +++ b/src/libdramsys/DRAMSys/configuration/memspec/MemSpecWideIO2.cpp @@ -45,43 +45,43 @@ using namespace tlm; MemSpecWideIO2::MemSpecWideIO2(const DRAMSys::Config::MemSpec &memSpec) : MemSpec(memSpec, MemoryType::WideIO2, - memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memarchitecturespec.entries.at("nbrOfChannels"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), 1, - memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfBanks") - * memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfRanks"), - memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), - tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), - tDQSS (tCK * memSpec.memTimingSpec.entries.at("DQSS")), - tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), - tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), - tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), - tRCpb (tCK * memSpec.memTimingSpec.entries.at("RCPB")), - tRCab (tCK * memSpec.memTimingSpec.entries.at("RCAB")), - tCKESR (tCK * memSpec.memTimingSpec.entries.at("CKESR")), - tXSR (tCK * memSpec.memTimingSpec.entries.at("XSR")), - tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), - tCCD (tCK * memSpec.memTimingSpec.entries.at("CCD")), - tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), - tRCD (tCK * memSpec.memTimingSpec.entries.at("RCD")), - tRPpb (tCK * memSpec.memTimingSpec.entries.at("RPPB")), - tRPab (tCK * memSpec.memTimingSpec.entries.at("RPAB")), - tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), - tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), - tWTR (tCK * memSpec.memTimingSpec.entries.at("WTR")), - tRRD (tCK * memSpec.memTimingSpec.entries.at("RRD")), - tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), - tREFI (tCK * static_cast(memSpec.memTimingSpec.entries.at("REFI") - * memSpec.memTimingSpec.entries.at("REFM"))), - tREFIpb (tCK * static_cast(memSpec.memTimingSpec.entries.at("REFIPB") - * memSpec.memTimingSpec.entries.at("REFM"))), - tRFCab (tCK * memSpec.memTimingSpec.entries.at("RFCAB")), - tRFCpb (tCK * memSpec.memTimingSpec.entries.at("RFCPB")), - tRTRS (tCK * memSpec.memTimingSpec.entries.at("RTRS")) + memSpec.memarchitecturespec.entries.at("nbrOfBanks"), + memSpec.memarchitecturespec.entries.at("nbrOfBanks") + * memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfRanks"), + memSpec.memarchitecturespec.entries.at("nbrOfDevices")), + tDQSCK (tCK * memSpec.memtimingspec.entries.at("DQSCK")), + tDQSS (tCK * memSpec.memtimingspec.entries.at("DQSS")), + tCKE (tCK * memSpec.memtimingspec.entries.at("CKE")), + tRL (tCK * memSpec.memtimingspec.entries.at("RL")), + tWL (tCK * memSpec.memtimingspec.entries.at("WL")), + tRCpb (tCK * memSpec.memtimingspec.entries.at("RCPB")), + tRCab (tCK * memSpec.memtimingspec.entries.at("RCAB")), + tCKESR (tCK * memSpec.memtimingspec.entries.at("CKESR")), + tXSR (tCK * memSpec.memtimingspec.entries.at("XSR")), + tXP (tCK * memSpec.memtimingspec.entries.at("XP")), + tCCD (tCK * memSpec.memtimingspec.entries.at("CCD")), + tRTP (tCK * memSpec.memtimingspec.entries.at("RTP")), + tRCD (tCK * memSpec.memtimingspec.entries.at("RCD")), + tRPpb (tCK * memSpec.memtimingspec.entries.at("RPPB")), + tRPab (tCK * memSpec.memtimingspec.entries.at("RPAB")), + tRAS (tCK * memSpec.memtimingspec.entries.at("RAS")), + tWR (tCK * memSpec.memtimingspec.entries.at("WR")), + tWTR (tCK * memSpec.memtimingspec.entries.at("WTR")), + tRRD (tCK * memSpec.memtimingspec.entries.at("RRD")), + tFAW (tCK * memSpec.memtimingspec.entries.at("FAW")), + tREFI (tCK * static_cast(memSpec.memtimingspec.entries.at("REFI") + * memSpec.memtimingspec.entries.at("REFM"))), + tREFIpb (tCK * static_cast(memSpec.memtimingspec.entries.at("REFIPB") + * memSpec.memtimingspec.entries.at("REFM"))), + tRFCab (tCK * memSpec.memtimingspec.entries.at("RFCAB")), + tRFCpb (tCK * memSpec.memtimingspec.entries.at("RFCPB")), + tRTRS (tCK * memSpec.memtimingspec.entries.at("RTRS")) { uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; uint64_t deviceSizeBytes = deviceSizeBits / 8; diff --git a/src/libdramsys/DRAMSys/controller/Controller.cpp b/src/libdramsys/DRAMSys/controller/Controller.cpp index 66c7b785..affa7540 100644 --- a/src/libdramsys/DRAMSys/controller/Controller.cpp +++ b/src/libdramsys/DRAMSys/controller/Controller.cpp @@ -546,7 +546,10 @@ void Controller::manageResponses() tlm_generic_payload* nextTransInRespQueue = respQueue->nextPayload(); if (nextTransInRespQueue != nullptr) { - numberOfBeatsServed += ControllerExtension::getBurstLength(*nextTransInRespQueue); + // Ignore ECC requests + if (nextTransInRespQueue->get_extension() == nullptr) + numberOfBeatsServed += ControllerExtension::getBurstLength(*nextTransInRespQueue); + if (ChildExtension::isChildTrans(*nextTransInRespQueue)) { tlm_generic_payload& parentTrans = ChildExtension::getParentTrans(*nextTransInRespQueue); diff --git a/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp b/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp index 60f1c6b0..83cd8f1c 100644 --- a/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp +++ b/src/libdramsys/DRAMSys/simulation/AddressDecoder.cpp @@ -37,53 +37,54 @@ */ #include "AddressDecoder.h" +#include "DRAMSys/configuration/Configuration.h" #include #include #include #include -AddressDecoder::AddressDecoder(const Configuration& config, const DRAMSys::Config::AddressMapping& addressMapping) +AddressDecoder::AddressDecoder(const DRAMSys::Config::AddressMapping &addressMapping, const MemSpec &memSpec) { - if (const auto& channelBits = addressMapping.channelBits) + if (const auto &channelBits = addressMapping.CHANNEL_BIT) { std::copy(channelBits->begin(), channelBits->end(), std::back_inserter(vChannelBits)); } - if (const auto& rankBits = addressMapping.rankBits) + if (const auto &rankBits = addressMapping.RANK_BIT) { std::copy(rankBits->begin(), rankBits->end(), std::back_inserter(vRankBits)); } - if (const auto& bankGroupBits = addressMapping.bankGroupBits) + if (const auto& bankGroupBits = addressMapping.BANKGROUP_BIT) { std::copy(bankGroupBits->begin(), bankGroupBits->end(), std::back_inserter(vBankGroupBits)); } - if (const auto& byteBits = addressMapping.byteBits) + if (const auto &byteBits = addressMapping.BYTE_BIT) { std::copy(byteBits->begin(), byteBits->end(), std::back_inserter(vByteBits)); } - if (const auto& xorBits = addressMapping.xorBits) + if (const auto &xorBits = addressMapping.XOR) { for (const auto& xorBit : *xorBits) { - vXor.emplace_back(xorBit.first, xorBit.second); + vXor.emplace_back(xorBit.FIRST, xorBit.SECOND); } } - if (const auto& bankBits = addressMapping.bankBits) + if (const auto &bankBits = addressMapping.BANK_BIT) { std::copy(bankBits->begin(), bankBits->end(), std::back_inserter(vBankBits)); } - if (const auto& rowBits = addressMapping.rowBits) + if (const auto &rowBits = addressMapping.ROW_BIT) { std::copy(rowBits->begin(), rowBits->end(), std::back_inserter(vRowBits)); } - if (const auto& columnBits = addressMapping.columnBits) + if (const auto &columnBits = addressMapping.COLUMN_BIT) { std::copy(columnBits->begin(), columnBits->end(), std::back_inserter(vColumnBits)); } @@ -113,8 +114,6 @@ AddressDecoder::AddressDecoder(const Configuration& config, const DRAMSys::Confi SC_REPORT_FATAL("AddressDecoder", "Not all address bits occur exactly once"); } - const MemSpec& memSpec = *config.memSpec; - unsigned highestByteBit = *std::max_element(vByteBits.begin(), vByteBits.end()); for (unsigned bitPosition = 0; bitPosition <= highestByteBit; bitPosition++) @@ -213,6 +212,41 @@ unsigned AddressDecoder::decodeChannel(uint64_t encAddr) const return channel; } +uint64_t AddressDecoder::encodeAddress(DecodedAddress decodedAddress) const +{ + // Convert absoulte addressing for bank, bankgroup to relative + decodedAddress.bankgroup = decodedAddress.bankgroup % bankgroupsPerRank; + decodedAddress.bank = decodedAddress.bank % banksPerGroup; + + uint64_t address = 0; + + for (unsigned i = 0; i < vChannelBits.size(); i++) + address |= ((decodedAddress.channel >> i) & 0x1) << vChannelBits[i]; + + for (unsigned i = 0; i < vRankBits.size(); i++) + address |= ((decodedAddress.rank >> i) & 0x1) << vRankBits[i]; + + for (unsigned i = 0; i < vBankGroupBits.size(); i++) + address |= ((decodedAddress.bankgroup >> i) & 0x1) << vBankGroupBits[i]; + + for (unsigned i = 0; i < vBankBits.size(); i++) + address |= ((decodedAddress.bank >> i) & 0x1) << vBankBits[i]; + + for (unsigned i = 0; i < vRowBits.size(); i++) + address |= ((decodedAddress.row >> i) & 0x1) << vRowBits[i]; + + for (unsigned i = 0; i < vColumnBits.size(); i++) + address |= ((decodedAddress.column >> i) & 0x1) << vColumnBits[i]; + + for (unsigned i = 0; i < vByteBits.size(); i++) + address |= ((decodedAddress.byte >> i) & 0x1) << vByteBits[i]; + + // TODO: XOR encoding + + return address; +} + + void AddressDecoder::print() const { std::cout << headline << std::endl; diff --git a/src/libdramsys/DRAMSys/simulation/AddressDecoder.h b/src/libdramsys/DRAMSys/simulation/AddressDecoder.h index 57f2f324..42a9f0d3 100644 --- a/src/libdramsys/DRAMSys/simulation/AddressDecoder.h +++ b/src/libdramsys/DRAMSys/simulation/AddressDecoder.h @@ -39,9 +39,8 @@ #ifndef ADDRESSDECODER_H #define ADDRESSDECODER_H -#include "DRAMSys/configuration/Configuration.h" - #include "DRAMSys/config/DRAMSysConfiguration.h" +#include "DRAMSys/configuration/Configuration.h" #include #include @@ -69,9 +68,10 @@ struct DecodedAddress class AddressDecoder { public: - AddressDecoder(const Configuration& config, const DRAMSys::Config::AddressMapping& addressMapping); + AddressDecoder(const DRAMSys::Config::AddressMapping &addressMapping, const MemSpec &memSpec); [[nodiscard]] DecodedAddress decodeAddress(uint64_t encAddr) const; [[nodiscard]] unsigned decodeChannel(uint64_t encAddr) const; + [[nodiscard]] uint64_t encodeAddress(DecodedAddress decodedAddress) const; void print() const; private: diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp b/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp index 7d02beab..25e23c70 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp +++ b/src/libdramsys/DRAMSys/simulation/DRAMSys.cpp @@ -86,9 +86,9 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, // Load configLib and initialize modules // Important: The memSpec needs to be the first configuration to be loaded! - config.loadMemSpec(configLib.memSpec); - config.loadMCConfig(configLib.mcConfig); - config.loadSimConfig(configLib.simConfig); + config.loadMemSpec(configLib.memspec); + config.loadMCConfig(configLib.mcconfig); + config.loadSimConfig(configLib.simconfig); // Setup the debug manager: setupDebugManager(config.simulationName); @@ -96,7 +96,7 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name& name, if (initAndBind) { // Instantiate all internal DRAMSys modules: - instantiateModules(configLib.addressMapping); + instantiateModules(configLib.addressmapping); // Connect all internal DRAMSys modules: bindSockets(); report(headline); @@ -157,7 +157,7 @@ void DRAMSys::setupDebugManager(NDEBUG_UNUSED(const std::string& traceName)) con void DRAMSys::instantiateModules(const ::DRAMSys::Config::AddressMapping& addressMapping) { - addressDecoder = std::make_unique(config, addressMapping); + addressDecoder = std::make_unique(addressMapping, *config.memSpec); addressDecoder->print(); // Create arbiter diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSys.h b/src/libdramsys/DRAMSys/simulation/DRAMSys.h index cec3a6d9..84343589 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSys.h +++ b/src/libdramsys/DRAMSys/simulation/DRAMSys.h @@ -70,6 +70,7 @@ public: const ::DRAMSys::Config::Configuration& configLib); const Configuration& getConfig() const; + const AddressDecoder &getAddressDecoder() const { return *addressDecoder; } protected: DRAMSys(const sc_core::sc_module_name& name, diff --git a/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp b/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp index 744fd1df..6e892378 100644 --- a/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp +++ b/src/libdramsys/DRAMSys/simulation/DRAMSysRecordable.cpp @@ -71,9 +71,9 @@ DRAMSysRecordable::DRAMSysRecordable(const sc_core::sc_module_name& name, const // is prepended to the simulation name if found. std::string traceName; - if (!configLib.simulationId.empty()) + if (!configLib.simulationid.empty()) { - std::string sid = configLib.simulationId; + std::string sid = configLib.simulationid; traceName = sid + '_' + config.simulationName; } else @@ -110,9 +110,14 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string& traceName, std::string dbName = std::string(name()) + "_" + traceName + "_ch" + std::to_string(i) + ".tdb"; std::string recorderName = "tlmRecorder" + std::to_string(i); + nlohmann::json mcconfig; + nlohmann::json memspec; + mcconfig[Config::McConfig::KEY] = configLib.mcconfig; + memspec[Config::MemSpec::KEY] = configLib.memspec; + tlmRecorders.emplace_back(recorderName, config, dbName); - tlmRecorders.back().recordMcConfig(::DRAMSys::Config::dump(configLib.mcConfig)); - tlmRecorders.back().recordMemspec(::DRAMSys::Config::dump(configLib.memSpec)); + tlmRecorders.back().recordMcConfig(mcconfig.dump()); + tlmRecorders.back().recordMemspec(memspec.dump()); tlmRecorders.back().recordTraceNames(config.simulationName); } } @@ -120,7 +125,7 @@ void DRAMSysRecordable::setupTlmRecorders(const std::string& traceName, void DRAMSysRecordable::instantiateModules(const std::string& traceName, const ::DRAMSys::Config::Configuration& configLib) { - addressDecoder = std::make_unique(config, configLib.addressMapping); + addressDecoder = std::make_unique(configLib.addressmapping, *config.memSpec); addressDecoder->print(); // Create and properly initialize TLM recorders. diff --git a/src/simulator/CMakeLists.txt b/src/simulator/CMakeLists.txt index 9c2f9032..2db1df94 100644 --- a/src/simulator/CMakeLists.txt +++ b/src/simulator/CMakeLists.txt @@ -43,15 +43,25 @@ project(DRAMSys_Simulator) file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp) file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp) -add_executable(DRAMSys ${SOURCE_FILES} ${HEADER_FILES}) -target_include_directories(DRAMSys PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +list(FILTER SOURCE_FILES EXCLUDE REGEX "main.cpp") + +add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES} ${HEADER_FILES}) + +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(${PROJECT_NAME} + PUBLIC + Threads::Threads + DRAMSys::libdramsys +) + +add_executable(DRAMSys + main.cpp +) target_link_libraries(DRAMSys PRIVATE - Threads::Threads - SystemC::systemc - DRAMSys::libdramsys + DRAMSys_Simulator ) build_source_group() -diagnostics_print(DRAMSys) \ No newline at end of file diff --git a/src/simulator/README.md b/src/simulator/README.md new file mode 100644 index 00000000..8f8712b2 --- /dev/null +++ b/src/simulator/README.md @@ -0,0 +1,19 @@ +# Simulator +The **standalone** simulator features a set of trace players, traffic generators and miscellaneous components that can be coupled with DRAMSys. + +## Concept +Initiators in the simulator are split up into two disctinct components: **RequestProducers** and **RequestIssuers**. + +**RequestProducers** are simple C++ classes that implement the `RequestProducer` interface. Upon calling the `nextRequest()` method of a producer, a new `Request` is either generated on-the-fly or constructed from a trace file. + +**RequestIssuers** are the SystemC modules that connect with DRAMSys. Issuers have no knowledge of where the requests are coming from. They simply call their `nextRequest()` callback that it has been passed in the constructor to obtain the next request to be sent to DRAMSys. Using this concept, the generation and the issuing of request is completely decoupled to make very flexible initiator designs possible. + +**Initiators** implement the `Initiator` interface, which describes how the initiator is bound to DRAMSys. This abstracts over the actual socket type used by the initiator. +Complex initiators may implement the interface directly, but for simple cases, there exists the templated `SimpleInitiator` class. This specialized initiator consists of only one producer and one issuer that operate together. The `StlPlayer` and `RowHammer` issuers make use of the `SimpleInitiator`. +The `TrafficGenerator` is one example of a direct implementation of the `Initiator` interface, as it consists of many producers (which represent the states of the state machine) but of only one issuer. + +**Requests** are an abstraction over the TLM payloads the issuer generates. A request describes whether it is a read or a write access or an internal `Stop` request that tells the initiator to terminate. +The **delay** field specifies the time that should pass between the issuance of the previous and the current request. + +## Configuration +A detailed description on how to configure the traffic generators of the simulator can be found [here](../../configs/README.md). diff --git a/src/simulator/main.cpp b/src/simulator/main.cpp new file mode 100644 index 00000000..66fbf903 --- /dev/null +++ b/src/simulator/main.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "simulator/Initiator.h" +#include "simulator/MemoryManager.h" +#include "simulator/SimpleInitiator.h" +#include "simulator/generator/TrafficGenerator.h" +#include "simulator/hammer/RowHammer.h" +#include "simulator/player/StlPlayer.h" +#include "simulator/util.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +static constexpr std::string_view TRACE_DIRECTORY = "traces"; + +int sc_main(int argc, char **argv) +{ + std::filesystem::path resourceDirectory = DRAMSYS_RESOURCE_DIR; + if (argc >= 3) + { + resourceDirectory = argv[2]; + } + + std::filesystem::path baseConfig = resourceDirectory / "ddr5-example.json"; + if (argc >= 2) + { + baseConfig = argv[1]; + } + + DRAMSys::Config::Configuration configuration = + DRAMSys::Config::from_path(baseConfig.c_str(), resourceDirectory.c_str()); + + if (!configuration.tracesetup.has_value()) + SC_REPORT_FATAL("Simulator", "No traffic initiators specified"); + + std::unique_ptr dramSys; + if (configuration.simconfig.DatabaseRecording) + { + dramSys = std::make_unique("DRAMSys", configuration); + } + else + { + dramSys = std::make_unique("DRAMSys", configuration); + } + + bool storageEnabled = dramSys->getConfig().storeMode == Configuration::StoreMode::Store; + MemoryManager memoryManager(storageEnabled); + + std::vector> initiators; + + unsigned int terminatedInitiators = 0; + auto termianteInitiator = [&initiators, &terminatedInitiators]() + { + terminatedInitiators++; + + if (terminatedInitiators == initiators.size()) + sc_core::sc_stop(); + }; + + uint64_t totalTransactions{}; + uint64_t transactionsFinished = 0; + auto transactionFinished = [&totalTransactions, &transactionsFinished]() + { + transactionsFinished++; + loadBar(transactionsFinished, totalTransactions); + }; + + for (auto const &initiator_config : configuration.tracesetup.value()) + { + uint64_t memorySize = dramSys->getConfig().memSpec->getSimMemSizeInBytes(); + unsigned int defaultDataLength = dramSys->getConfig().memSpec->defaultBytesPerBurst; + + auto initiator = std::visit( + [=, &memoryManager](auto &&config) -> std::unique_ptr + { + using T = std::decay_t; + if constexpr (std::is_same_v || + std::is_same_v) + { + return std::make_unique(config, + memoryManager, + memorySize, + defaultDataLength, + transactionFinished, + termianteInitiator); + } + else if constexpr (std::is_same_v) + { + std::filesystem::path tracePath = + resourceDirectory / TRACE_DIRECTORY / config.name; + + StlPlayer::TraceType traceType; + + auto extension = tracePath.extension(); + if (extension == ".stl") + traceType = StlPlayer::TraceType::Absolute; + else if (extension == ".rtl") + traceType = StlPlayer::TraceType::Relative; + else + { + std::string report = extension.string() + " is not a valid trace format."; + SC_REPORT_FATAL("Simulator", report.c_str()); + } + + StlPlayer player( + tracePath.c_str(), config.clkMhz, defaultDataLength, traceType, false); + + return std::make_unique>(config.name.c_str(), + memoryManager, + std::nullopt, + std::nullopt, + transactionFinished, + termianteInitiator, + std::move(player)); + } + else if constexpr (std::is_same_v) + { + RowHammer hammer( + config.numRequests, config.clkMhz, config.rowIncrement, defaultDataLength); + + return std::make_unique>(config.name.c_str(), + memoryManager, + 1, + 1, + transactionFinished, + termianteInitiator, + std::move(hammer)); + } + }, + initiator_config); + + totalTransactions += initiator->totalRequests(); + + initiator->bind(dramSys->tSocket); + initiators.push_back(std::move(initiator)); + } + + // Store the starting of the simulation in wall-clock time: + auto start = std::chrono::high_resolution_clock::now(); + + // Start the SystemC simulation + sc_set_stop_mode(sc_core::SC_STOP_FINISH_DELTA); + sc_core::sc_start(); + + if (!sc_core::sc_end_of_simulation_invoked()) + { + SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()"); + sc_core::sc_stop(); + } + + auto finish = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = finish - start; + std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl; + + return 0; +} diff --git a/src/simulator/simulator/Cache.cpp b/src/simulator/simulator/Cache.cpp new file mode 100644 index 00000000..06739cfe --- /dev/null +++ b/src/simulator/simulator/Cache.cpp @@ -0,0 +1,639 @@ +#include "Cache.h" +#include "MemoryManager.h" + +#include +#include +#include +#include +#include +#include + +using namespace tlm; +using namespace sc_core; + +DECLARE_EXTENDED_PHASE(HIT_HANDLING); +DECLARE_EXTENDED_PHASE(MISS_HANDLING); + +Cache::Cache(const sc_module_name &name, + std::size_t size, + std::size_t associativity, + std::size_t lineSize, + std::size_t mshrDepth, + std::size_t writeBufferDepth, + std::size_t maxTargetListSize, + bool storageEnabled, + sc_core::sc_time cycleTime, + std::size_t hitCycles, + MemoryManager &memoryManager) : + sc_module(name), + payloadEventQueue(this, &Cache::peqCallback), + storageEnabled(storageEnabled), + cycleTime(cycleTime), + hitLatency(cycleTime * static_cast(hitCycles)), + size(size), + associativity(associativity), + lineSize(lineSize), + numberOfSets(size / (lineSize * associativity)), + indexShifts(static_cast(std::log2(lineSize))), + indexMask(numberOfSets - 1), + tagShifts(indexShifts + static_cast(std::log2(numberOfSets))), + mshrDepth(mshrDepth), + writeBufferDepth(writeBufferDepth), + maxTargetListSize(maxTargetListSize), + memoryManager(memoryManager) +{ + iSocket.register_nb_transport_bw(this, &Cache::nb_transport_bw); + tSocket.register_nb_transport_fw(this, &Cache::nb_transport_fw); + + lineTable = std::vector>(numberOfSets, std::vector(associativity)); + + if (storageEnabled) + { + dataMemory.reserve(size); + + for (std::size_t set = 0; set < lineTable.size(); set++) + { + for (std::size_t way = 0; way < lineTable[set].size(); way++) + lineTable[set][way].dataPtr = dataMemory.data() + set * associativity * lineSize + way * lineSize; + } + } +} + +tlm_sync_enum Cache::nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay) // core side ---> +{ + if (phase == BEGIN_REQ) + { + if (trans.get_data_length() > lineSize) + { + SC_REPORT_FATAL(name(), "Accesses larger than line size in non-blocking mode not supported!"); + } + + trans.acquire(); + } + + // TODO: early completion would be possible + payloadEventQueue.notify(trans, phase, ceilDelay(delay)); + + return TLM_ACCEPTED; +} + +tlm_sync_enum Cache::nb_transport_bw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &bwDelay) // DRAM side <--- +{ + // TODO: early completion would be possible + payloadEventQueue.notify(trans, phase, ceilDelay(bwDelay)); + + return TLM_ACCEPTED; +} + +void Cache::peqCallback(tlm_generic_payload &trans, const tlm_phase &phase) +{ + if (phase == BEGIN_REQ) // core side ---> + { + assert(!endRequestPending); + fetchLineAndSendEndRequest(trans); + return; + } + else if (phase == END_REQ) // <--- DRAM side + { + lastEndReq = sc_time_stamp(); + clearInitiatorBackpressureAndProcessBuffers(); + return; + } + else if (phase == BEGIN_RESP && &trans == requestInProgress) // <--- DRAM side + { + // Shortcut, 2 phases in one + clearInitiatorBackpressureAndProcessBuffers(); + sendEndResponseAndFillLine(trans); + return; + } + else if (phase == BEGIN_RESP) // <--- DRAM side + { + sendEndResponseAndFillLine(trans); + return; + } + else if (phase == END_RESP) // core side ---> + { + clearTargetBackpressureAndProcessLines(trans); + return; + } + else if (phase == HIT_HANDLING) // direct hit, account for the hit delay + { + index_t index; + tag_t tag; + std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address()); + + hitQueue.emplace_back(index, tag, &trans); + processHitQueue(); + } + else if (phase == MISS_HANDLING) // fetched MSHR entry available, account for the hit delay + { + accessCacheAndSendResponse(trans); + + index_t index; + tag_t tag; + std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address()); + + auto mshrIt = std::find_if(mshrQueue.begin(), mshrQueue.end(), + [index, tag](const Mshr &mshr) { return mshr.index == index && mshr.tag == tag; }); + + assert(mshrIt != mshrQueue.end()); + mshrIt->hitDelayAccounted = true; + + if (mshrIt->requestList.empty()) + { + mshrQueue.erase(mshrIt); + + if (endRequestPending != nullptr && hasBufferSpace()) + { + payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME); + endRequestPending = nullptr; + } + } + } + else + { + SC_REPORT_FATAL("Cache", "PEQ was triggered with unknown phase"); + } +} + +/// Handler for begin request from core side. +void Cache::fetchLineAndSendEndRequest(tlm_generic_payload &trans) +{ + if (hasBufferSpace()) + { + index_t index; + tag_t tag; + std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address()); + + auto mshrEntry = + std::find_if(mshrQueue.begin(), mshrQueue.end(), + [index, tag](const Mshr &entry) { return (index == entry.index) && (tag == entry.tag); }); + + if (isHit(index, tag)) + { + numberOfHits++; + + // Handle hit + // Account for the 1 cycle accept delay. + payloadEventQueue.notify(trans, HIT_HANDLING, hitLatency + cycleTime); + } + else if (mshrEntry != mshrQueue.end()) // Miss with outstanding previous Miss, noted in MSHR + { + numberOfSecondaryMisses++; + assert(isAllocated(index, tag)); + + // A fetch for this cache line is already in progress + // Add request to the existing Mshr entry + + if (mshrEntry->requestList.size() == maxTargetListSize) + { + // Insertion into requestList in mshrEntry not possible. + endRequestPending = &trans; + return; + } + + mshrEntry->requestList.emplace_back(&trans); + } + else // Miss without MSHR entry: + { + numberOfPrimaryMisses++; + assert(!isAllocated(index, tag)); + + // Cache miss and no fetch in progress. + // So evict line and allocate empty line. + auto evictedLine = evictLine(index); + if (!evictedLine) + { + // Line eviction not possible. + endRequestPending = &trans; + return; + } + + allocateLine(evictedLine, tag); + mshrQueue.emplace_back(index, tag, &trans); + + processMshrQueue(); + processWriteBuffer(); + } + + tlm_phase bwPhase = END_REQ; + sc_time bwDelay = SC_ZERO_TIME; + tSocket->nb_transport_bw(trans, bwPhase, bwDelay); + } + else + { + endRequestPending = &trans; + } +} + +/// Handler for end request from DRAM side. +void Cache::clearInitiatorBackpressureAndProcessBuffers() +{ + requestInProgress = nullptr; + + processMshrQueue(); + processWriteBuffer(); +} + +/// Handler for begin response from DRAM side. +void Cache::sendEndResponseAndFillLine(tlm_generic_payload &trans) +{ + tlm_phase fwPhase = END_RESP; + sc_time fwDelay = SC_ZERO_TIME; + iSocket->nb_transport_fw(trans, fwPhase, fwDelay); + + if (trans.is_read()) + { + fillLine(trans); + processMshrResponse(); + } + + trans.release(); +} + +/// Handler for end response from core side. +void Cache::clearTargetBackpressureAndProcessLines(tlm_generic_payload &trans) +{ + trans.release(); + tSocketBackpressure = false; + + processHitQueue(); + processMshrResponse(); + + // When the cache currently only handles hits from the hit queue and + // no other requests to the DRAM side are pending, there is a chance + // that a endRequestPending will never be served. + // To circumvent this, pass it into the system again at this point. + if (endRequestPending != nullptr && hasBufferSpace()) + { + payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME); + endRequestPending = nullptr; + } +} + +unsigned int Cache::transport_dbg(tlm_generic_payload &trans) +{ + return iSocket->transport_dbg(trans); +} + +bool Cache::isHit(index_t index, tag_t tag) const +{ + return std::find_if(lineTable[index].begin(), lineTable[index].end(), + [tag](const CacheLine &cacheLine) + { return (cacheLine.tag == tag) && cacheLine.valid; }) != lineTable[index].end(); +} + +bool Cache::isHit(uint64_t address) const +{ + index_t index; + tag_t tag; + std::tie(index, tag, std::ignore) = decodeAddress(address); + + return isHit(index, tag); +} + +std::tuple Cache::decodeAddress(uint64_t address) const +{ + return {(address >> indexShifts) & indexMask, address >> tagShifts, address % lineSize}; +} + +uint64_t Cache::encodeAddress(Cache::index_t index, Cache::tag_t tag, Cache::lineOffset_t lineOffset) const +{ + return static_cast(tag << tagShifts) | index << indexShifts | lineOffset; +} + +/// Write data to an available cache line, update flags +void Cache::writeLine( + index_t index, tag_t tag, lineOffset_t lineOffset, unsigned int dataLength, const unsigned char *dataPtr) +{ + // SC_REPORT_ERROR("cache", "Write to Cache not allowed!"); + + CacheLine ¤tLine = *std::find_if(lineTable[index].begin(), lineTable[index].end(), + [tag](const CacheLine &cacheLine) { return cacheLine.tag == tag; }); + + assert(currentLine.valid); + currentLine.lastAccessTime = sc_time_stamp(); + currentLine.dirty = true; + + if (storageEnabled) + std::copy(dataPtr, dataPtr + dataLength, currentLine.dataPtr + lineOffset); +} + +/// Read data from an available cache line, update flags +void Cache::readLine(index_t index, tag_t tag, lineOffset_t lineOffset, unsigned int dataLength, unsigned char *dataPtr) +{ + CacheLine ¤tLine = *std::find_if(lineTable[index].begin(), lineTable[index].end(), + [tag](const CacheLine &cacheLine) { return cacheLine.tag == tag; }); + + assert(currentLine.valid); + currentLine.lastAccessTime = sc_time_stamp(); + + if (storageEnabled) + std::copy(currentLine.dataPtr + lineOffset, currentLine.dataPtr + lineOffset + dataLength, dataPtr); +} + +/// Tries to evict oldest line (insert into write memory) +/// Returns the line or a nullptr if not possible +Cache::CacheLine *Cache::evictLine(Cache::index_t index) +{ + CacheLine &oldestLine = *std::min_element(lineTable[index].begin(), lineTable[index].end(), + [](const CacheLine &lhs, const CacheLine &rhs) + { return lhs.lastAccessTime < rhs.lastAccessTime; }); + + if (oldestLine.allocated && !oldestLine.valid) + { + // oldestline is allocated but not yet valid -> fetch in progress + return nullptr; + } + else if (std::find_if(mshrQueue.begin(), mshrQueue.end(), + [index, oldestLine](const Mshr &entry) + { return (index == entry.index) && (oldestLine.tag == entry.tag); }) != mshrQueue.end()) + { + // TODO: solve this in a more clever way + // There are still entries in mshrQueue to the oldest line -> do not evict it + return nullptr; + } + else if (std::find_if(hitQueue.begin(), hitQueue.end(), + [index, oldestLine](const BufferEntry &entry) + { return (index == entry.index) && (oldestLine.tag == entry.tag); }) != hitQueue.end()) + { + // TODO: solve this in a more clever way + // There are still hits in hitQueue to the oldest line -> do not evict it + return nullptr; + } + else + { + if (oldestLine.valid && oldestLine.dirty) + { + auto &wbTrans = memoryManager.allocate(lineSize); + wbTrans.acquire(); + wbTrans.set_address(encodeAddress(index, oldestLine.tag)); + wbTrans.set_write(); + wbTrans.set_data_length(lineSize); + wbTrans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + if (storageEnabled) + std::copy(oldestLine.dataPtr, oldestLine.dataPtr + lineSize, wbTrans.get_data_ptr()); + + writeBuffer.emplace_back(index, oldestLine.tag, &wbTrans); + } + + oldestLine.allocated = false; + oldestLine.valid = false; + oldestLine.dirty = false; + + return &oldestLine; + } +} + +/// Align address to cache line size +uint64_t Cache::getAlignedAddress(uint64_t address) const +{ + return address - (address % lineSize); +} + +/// Issue read requests for entries in the MshrQueue to the target +void Cache::processMshrQueue() +{ + if (!requestInProgress && !mshrQueue.empty()) + { + // Get the first entry that wasn't already issued to the target + auto mshrIt = std::find_if(mshrQueue.begin(), mshrQueue.end(), [](const Mshr &entry) { return !entry.issued; }); + + if (mshrIt == mshrQueue.end()) + return; + + // Note: This is the same address for all entries in the requests list + uint64_t alignedAddress = getAlignedAddress(mshrIt->requestList.front()->get_address()); + + index_t index; + tag_t tag; + std::tie(index, tag, std::ignore) = decodeAddress(alignedAddress); + + // Search through the writeBuffer in reverse order to get the most recent entry. + auto writeBufferEntry = std::find_if(writeBuffer.rbegin(), writeBuffer.rbegin(), + [index, tag](const BufferEntry &entry) + { return (index == entry.index) && (tag == entry.tag); }); + + if (writeBufferEntry != writeBuffer.rbegin()) + { + // There is an entry for the required line in the write buffer. + // Snoop into it and get the data from there instead of the dram. + mshrIt->issued = true; + clearInitiatorBackpressureAndProcessBuffers(); + + fillLine(*writeBufferEntry->trans); + processMshrResponse(); + + return; + } + + // Prevents that the cache line will get fetched multiple times from the target + mshrIt->issued = true; + + auto &fetchTrans = memoryManager.allocate(lineSize); + fetchTrans.acquire(); + fetchTrans.set_read(); + fetchTrans.set_data_length(lineSize); + fetchTrans.set_streaming_width(lineSize); + fetchTrans.set_address(alignedAddress); + fetchTrans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + tlm_phase fwPhase = BEGIN_REQ; + + // Always account for the cycle as either we just received the BEGIN_REQ + // or we cleared the backpressure from another END_REQ. + sc_time fwDelay = cycleTime; + + requestInProgress = &fetchTrans; + tlm_sync_enum returnValue = iSocket->nb_transport_fw(fetchTrans, fwPhase, fwDelay); + + if (returnValue == tlm::TLM_UPDATED) + { + // END_REQ or BEGIN_RESP + payloadEventQueue.notify(fetchTrans, fwPhase, fwDelay); + } + else if (returnValue == tlm::TLM_COMPLETED) + { + clearInitiatorBackpressureAndProcessBuffers(); + + fillLine(fetchTrans); + processMshrResponse(); + + fetchTrans.release(); + } + + if (endRequestPending != nullptr && hasBufferSpace()) + { + payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME); + endRequestPending = nullptr; + } + } +} + +/// Processes writeBuffer (dirty cache line evictions) +void Cache::processWriteBuffer() +{ + if (!requestInProgress && !writeBuffer.empty()) + { + tlm_generic_payload &wbTrans = *writeBuffer.front().trans; + + tlm_phase fwPhase = BEGIN_REQ; + sc_time fwDelay = (lastEndReq == sc_time_stamp()) ? cycleTime : SC_ZERO_TIME; + + requestInProgress = &wbTrans; + tlm_sync_enum returnValue = iSocket->nb_transport_fw(wbTrans, fwPhase, fwDelay); + + if (returnValue == tlm::TLM_UPDATED) + { + // END_REQ or BEGIN_RESP + payloadEventQueue.notify(wbTrans, fwPhase, fwDelay); + } + else if (returnValue == tlm::TLM_COMPLETED) + { + clearInitiatorBackpressureAndProcessBuffers(); + wbTrans.release(); + } + + if (endRequestPending != nullptr && hasBufferSpace()) + { + payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME); + endRequestPending = nullptr; + } + + writeBuffer.pop_front(); + } +} + +/// Fill allocated cache line with data from memory +void Cache::fillLine(tlm_generic_payload &trans) +{ + index_t index; + tag_t tag; + std::tie(index, tag, std::ignore) = decodeAddress(trans.get_address()); + + CacheLine &allocatedLine = + *std::find_if(lineTable[index].begin(), lineTable[index].end(), + [tag](const CacheLine &cacheLine) { return cacheLine.allocated && cacheLine.tag == tag; }); + + allocatedLine.valid = true; + allocatedLine.dirty = false; + + if (storageEnabled) + std::copy(trans.get_data_ptr(), trans.get_data_ptr() + lineSize, allocatedLine.dataPtr); +} + +/// Make cache access for pending hits +void Cache::processHitQueue() +{ + if (!tSocketBackpressure && !hitQueue.empty()) + { + auto hit = hitQueue.front(); + hitQueue.pop_front(); + + accessCacheAndSendResponse(*hit.trans); + } +} + +/// Access the available cache line and send the response +void Cache::accessCacheAndSendResponse(tlm_generic_payload &trans) +{ + assert(!tSocketBackpressure); + assert(isHit(trans.get_address())); + + auto [index, tag, lineOffset] = decodeAddress(trans.get_address()); + + if (trans.is_read()) + readLine(index, tag, lineOffset, trans.get_data_length(), trans.get_data_ptr()); + else + writeLine(index, tag, lineOffset, trans.get_data_length(), trans.get_data_ptr()); + + tlm_phase bwPhase = BEGIN_RESP; + sc_time bwDelay = SC_ZERO_TIME; + + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + tlm_sync_enum returnValue = tSocket->nb_transport_bw(trans, bwPhase, bwDelay); + if (returnValue == tlm::TLM_UPDATED) // TODO tlm_completed + payloadEventQueue.notify(trans, bwPhase, bwDelay); + + tSocketBackpressure = true; +} + +/// Allocates an empty line for later filling (lastAccessTime = sc_max_time()) +void Cache::allocateLine(CacheLine *line, tag_t tag) +{ + line->allocated = true; + line->tag = tag; + line->lastAccessTime = sc_max_time(); +} + +/// Checks whether a line with the corresponding tag is already allocated (fetch in progress or already valid) +bool Cache::isAllocated(Cache::index_t index, Cache::tag_t tag) const +{ + return std::find_if(lineTable[index].begin(), lineTable[index].end(), + [tag](const CacheLine &cacheLine) + { return (cacheLine.tag == tag) && cacheLine.allocated; }) != lineTable[index].end(); +} + +/// Process oldest hit in mshrQueue, accept pending request from initiator +void Cache::processMshrResponse() +{ + if (!tSocketBackpressure) // TODO: Bedingung eigentlich zu streng, wenn man Hit delay berücksichtigt. + { + const auto hitIt = std::find_if(mshrQueue.begin(), mshrQueue.end(), + [this](const Mshr &entry) { return isHit(entry.index, entry.tag); }); + + // In case there are hits in mshrActive, handle them. Otherwise try again later. + if (hitIt == mshrQueue.end()) + return; + + // Another MSHR target already started the modeling of the hit delay. + // Try again later. + if (hitIt->hitDelayStarted && !hitIt->hitDelayAccounted) + return; + + // Get the first request in the list and respond to it + tlm_generic_payload &returnTrans = *hitIt->requestList.front(); + hitIt->requestList.pop_front(); + + if (hitIt->hitDelayAccounted) + accessCacheAndSendResponse(returnTrans); + else + { + hitIt->hitDelayStarted = true; + payloadEventQueue.notify(returnTrans, MISS_HANDLING, hitLatency); + return; + } + + if (hitIt->requestList.empty()) + { + mshrQueue.erase(hitIt); + + if (endRequestPending != nullptr && hasBufferSpace()) + { + payloadEventQueue.notify(*endRequestPending, BEGIN_REQ, SC_ZERO_TIME); + endRequestPending = nullptr; + } + } + } +} + +/// Checks whether both mshrActive and writeBuffer have memory space +bool Cache::hasBufferSpace() const +{ + return mshrQueue.size() < mshrDepth && writeBuffer.size() < writeBufferDepth; +} + +sc_time Cache::ceilTime(const sc_time &inTime) const +{ + return std::ceil(inTime / cycleTime) * cycleTime; +} + +sc_time Cache::ceilDelay(const sc_time &inDelay) const +{ + sc_time inTime = sc_time_stamp() + inDelay; + sc_time outTime = ceilTime(inTime); + sc_time outDelay = outTime - sc_time_stamp(); + return outDelay; +} diff --git a/src/simulator/simulator/Cache.h b/src/simulator/simulator/Cache.h new file mode 100644 index 00000000..845986c9 --- /dev/null +++ b/src/simulator/simulator/Cache.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Christian Malek + * Derek Christ + */ + +#pragma once + +#include "MemoryManager.h" + +#include +#include +#include +#include +#include +#include +#include + +class Cache : public sc_core::sc_module +{ +public: + tlm_utils::simple_initiator_socket iSocket; + tlm_utils::simple_target_socket tSocket; + + Cache(const sc_core::sc_module_name &name, + std::size_t size, + std::size_t associativity, + std::size_t lineSize, + std::size_t mshrDepth, + std::size_t writeBufferDepth, + std::size_t maxTargetListSize, + bool storageEnabled, + sc_core::sc_time cycleTime, + std::size_t hitCycles, + MemoryManager &memoryManager); + SC_HAS_PROCESS(Cache); + +private: + void peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase); + + tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &fwDelay); + tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &bwDelay); + unsigned int transport_dbg(tlm::tlm_generic_payload &trans); + + void fetchLineAndSendEndRequest(tlm::tlm_generic_payload &trans); + void clearInitiatorBackpressureAndProcessBuffers(); + void sendEndResponseAndFillLine(tlm::tlm_generic_payload &trans); + void clearTargetBackpressureAndProcessLines(tlm::tlm_generic_payload &trans); + + tlm_utils::peq_with_cb_and_phase payloadEventQueue; + + const bool storageEnabled; + sc_core::sc_time cycleTime; + const sc_core::sc_time hitLatency; + const std::size_t size; + + // Lines per set. + const std::size_t associativity; + + const std::size_t lineSize; + const std::size_t numberOfSets; + const std::size_t indexShifts; + const std::size_t indexMask; + const std::size_t tagShifts; + + const std::size_t mshrDepth; + const std::size_t writeBufferDepth; + const std::size_t maxTargetListSize; + + using index_t = std::uint64_t; + using tag_t = std::uint64_t; + using lineOffset_t = std::uint64_t; + + struct CacheLine + { + tag_t tag = 0; + unsigned char *dataPtr = nullptr; + bool allocated = false; + bool valid = false; + bool dirty = false; + sc_core::sc_time lastAccessTime = sc_core::SC_ZERO_TIME; + }; + + std::vector> lineTable; + std::vector dataMemory; + + bool isHit(index_t index, tag_t tag) const; + bool isHit(std::uint64_t address) const; + + void writeLine(index_t index, + tag_t tag, + lineOffset_t lineOffset, + unsigned int dataLength, + const unsigned char *dataPtr); + + void readLine(index_t index, + tag_t tag, + lineOffset_t lineOffset, + unsigned int dataLength, + unsigned char *dataPtr); + + CacheLine *evictLine(index_t index); + + std::tuple decodeAddress(std::uint64_t address) const; + std::uint64_t encodeAddress(index_t index, tag_t tag, lineOffset_t lineOffset = 0) const; + + struct BufferEntry + { + index_t index; + tag_t tag; + tlm::tlm_generic_payload *trans; + + BufferEntry(index_t index, tag_t tag, tlm::tlm_generic_payload *trans) + : index(index), tag(tag), trans(trans) + { + } + }; + + struct Mshr + { + index_t index; + tag_t tag; + std::list requestList; + + /// Whether the Mshr entry was already issued to the target. + bool issued = false; + + /// Whether the hit delay was already accounted for. + /// Used to determine if the next entry in the request list + /// should be sent out without the hit delay. + bool hitDelayAccounted = false; + + /// Whether the hit delay is being awaited on. + /// Used prevent other MSHR targets to wait on the hit + /// delay when it is already being waited on. + bool hitDelayStarted = false; + + Mshr(index_t index, tag_t tag, tlm::tlm_generic_payload *request) + : index(index), tag(tag), requestList{request} + { + } + }; + + std::deque mshrQueue; + std::deque hitQueue; + + using WriteBuffer = std::list; + WriteBuffer writeBuffer; + + uint64_t numberOfHits = 0; + uint64_t numberOfPrimaryMisses = 0; + uint64_t numberOfSecondaryMisses = 0; + + std::uint64_t getAlignedAddress(std::uint64_t address) const; + + void processMshrResponse(); + void processWriteBuffer(); + void processHitQueue(); + void processMshrQueue(); + + bool tSocketBackpressure = false; + + // Request to the target + tlm::tlm_generic_payload *requestInProgress = nullptr; + + // Backpressure on initiator + tlm::tlm_generic_payload *endRequestPending = nullptr; + + sc_core::sc_time lastEndReq = sc_core::sc_max_time(); + + void fillLine(tlm::tlm_generic_payload &trans); + void accessCacheAndSendResponse(tlm::tlm_generic_payload &trans); + void allocateLine(CacheLine *line, tag_t tag); + + bool isAllocated(index_t index, tag_t tag) const; + bool hasBufferSpace() const; + + sc_core::sc_time ceilTime(const sc_core::sc_time &inTime) const; + sc_core::sc_time ceilDelay(const sc_core::sc_time &inDelay) const; + + MemoryManager &memoryManager; +}; diff --git a/src/simulator/simulator/EccModule.cpp b/src/simulator/simulator/EccModule.cpp new file mode 100644 index 00000000..6b3caa4f --- /dev/null +++ b/src/simulator/simulator/EccModule.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Christian Malek + * Derek Christ + */ + +#include "EccModule.h" + +#include "DRAMSys/common/dramExtensions.h" + +#include + +using namespace sc_core; +using namespace tlm; + +EccModule::EccModule(sc_module_name name, AddressDecoder const &addressDecoder) : + sc_core::sc_module(name), + payloadEventQueue(this, &EccModule::peqCallback), + addressDecoder(addressDecoder), + memoryManager(false) +{ + iSocket.register_nb_transport_bw(this, &EccModule::nb_transport_bw); + tSocket.register_nb_transport_fw(this, &EccModule::nb_transport_fw); +} + +tlm::tlm_sync_enum EccModule::nb_transport_fw(tlm::tlm_generic_payload &payload, + tlm::tlm_phase &phase, + sc_core::sc_time &fwDelay) +{ + if (phase == BEGIN_REQ) + { + payload.acquire(); + } + + payloadEventQueue.notify(payload, phase, fwDelay); + return TLM_ACCEPTED; +} + +tlm::tlm_sync_enum EccModule::nb_transport_bw(tlm::tlm_generic_payload &payload, + tlm::tlm_phase &phase, + sc_core::sc_time &bwDelay) +{ + payloadEventQueue.notify(payload, phase, bwDelay); + return TLM_ACCEPTED; +} + +void EccModule::peqCallback(tlm::tlm_generic_payload &cbPayload, const tlm::tlm_phase &cbPhase) +{ + if (cbPhase == BEGIN_REQ) // from initiator + { + // Put transaction into latency map + payloadMap.emplace(&cbPayload, sc_time_stamp()); + + if (!targetBusy) + { + targetBusy = true; + + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = SC_ZERO_TIME; + + DecodedAddress decodedAddress = addressDecoder.decodeAddress(cbPayload.get_address()); + decodedAddress = calculateOffsetAddress(decodedAddress); + + // Update the original address to account for the offsets + cbPayload.set_address(addressDecoder.encodeAddress(decodedAddress)); + + auto currentBlock = alignToBlock(decodedAddress.column); + + // In case there is no entry yet. + activeEccBlocks.try_emplace(decodedAddress.bank); + +#ifdef ECC_ENABLE + if (!activeEccBlock(decodedAddress.bank, decodedAddress.row, currentBlock)) + { + blockedRequest = &cbPayload; + + auto &eccFifo = activeEccBlocks[decodedAddress.bank]; + eccFifo.push_back({currentBlock, decodedAddress.row}); + + // Only hold 4 elements at max. + if (eccFifo.size() >= 4) + eccFifo.pop_front(); + + tlm::tlm_generic_payload *eccPayload = generateEccPayload(decodedAddress); + + iSocket->nb_transport_fw(*eccPayload, tPhase, tDelay); + } + else +#endif + { + iSocket->nb_transport_fw(cbPayload, tPhase, tDelay); + } + } + else + { + pendingRequest = &cbPayload; + } + } + else if (cbPhase == END_REQ) // from target + { + // Send payload to inititator in case it is not an ECC transaction + if (cbPayload.get_extension() == nullptr) + { + tlm_phase tPhase = END_REQ; + sc_time tDelay = SC_ZERO_TIME; + + tSocket->nb_transport_bw(cbPayload, tPhase, tDelay); + } + + if (blockedRequest != nullptr) + { + tlm_generic_payload &tPayload = *blockedRequest; + blockedRequest = nullptr; + + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = SC_ZERO_TIME; + + iSocket->nb_transport_fw(tPayload, tPhase, tDelay); + + // Do not attempt to send another pending request and hold targetBusy high + return; + } + + if (pendingRequest != nullptr) + { + tlm_generic_payload &tPayload = *pendingRequest; + + tlm_phase tPhase = BEGIN_REQ; + sc_time tDelay = SC_ZERO_TIME; + + DecodedAddress decodedAddress = addressDecoder.decodeAddress(tPayload.get_address()); + decodedAddress = calculateOffsetAddress(decodedAddress); + auto currentBlock = alignToBlock(decodedAddress.column); +#ifdef ECC_ENABLE + if (!activeEccBlock(decodedAddress.bank, decodedAddress.row, currentBlock)) + { + blockedRequest = pendingRequest; + pendingRequest = nullptr; + + auto &eccFifo = activeEccBlocks[decodedAddress.bank]; + eccFifo.push_back({currentBlock, decodedAddress.row}); + + // Only hold 4 elements at max. + if (eccFifo.size() >= 4) + eccFifo.pop_front(); + + tlm::tlm_generic_payload *eccPayload = generateEccPayload(decodedAddress); + + iSocket->nb_transport_fw(*eccPayload, tPhase, tDelay); + } + else +#endif + { + iSocket->nb_transport_fw(tPayload, tPhase, tDelay); + pendingRequest = nullptr; + } + } + else + { + assert(!pendingRequest); + assert(!blockedRequest); + targetBusy = false; + } + } + else if (cbPhase == BEGIN_RESP) // from memory controller + { + // Send payload to inititator in case it is not an ECC transaction + if (cbPayload.get_extension() == nullptr) + { + tlm_phase tPhase = BEGIN_RESP; + sc_time tDelay = SC_ZERO_TIME; + + tlm_sync_enum returnValue = tSocket->nb_transport_bw(cbPayload, tPhase, tDelay); + + // Early completion from initiator + if (returnValue == TLM_UPDATED) + { + payloadEventQueue.notify(cbPayload, tPhase, tDelay); + } + + Latency latency = sc_time_stamp() - payloadMap.at(&cbPayload); + payloadMap.erase(&cbPayload); + + latency = roundLatency(latency); + latencyMap.try_emplace(latency, 0); + latencyMap.at(latency)++; + } + else + { + // Send END_RESP by ourselfes + tlm_phase tPhase = END_RESP; + sc_time tDelay = SC_ZERO_TIME; + + iSocket->nb_transport_fw(cbPayload, tPhase, tDelay); + } + } + else if (cbPhase == END_RESP) // from initiator + { + { + tlm_phase tPhase = END_RESP; + sc_time tDelay = SC_ZERO_TIME; + + iSocket->nb_transport_fw(cbPayload, tPhase, tDelay); + } + + cbPayload.release(); + } + else + { + SC_REPORT_FATAL(0, "Payload event queue in arbiter was triggered with unknown phase"); + } +} + +tlm::tlm_generic_payload *EccModule::generateEccPayload(DecodedAddress decodedAddress) +{ + unsigned int eccAtom = decodedAddress.column / 512; + uint64_t eccColumn = 1792 + eccAtom * 32; + + decodedAddress.column = eccColumn; + uint64_t eccAddress = addressDecoder.encodeAddress(decodedAddress); + + tlm_generic_payload &payload = memoryManager.allocate(32); + payload.acquire(); + payload.set_address(eccAddress); + payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + payload.set_dmi_allowed(false); + payload.set_byte_enable_length(0); + payload.set_data_length(32); + payload.set_streaming_width(32); + payload.set_command(tlm::TLM_READ_COMMAND); + payload.set_extension(new EccExtension); + + return &payload; +} + +unsigned int EccModule::alignToBlock(unsigned column) +{ + return column & ~(512 - 1); +} + +DecodedAddress EccModule::calculateOffsetAddress(DecodedAddress decodedAddress) +{ + unsigned int newRow = + std::floor((decodedAddress.row * 256 + decodedAddress.column) / 1792) + decodedAddress.row; + unsigned int newColumn = (decodedAddress.row * 256 + decodedAddress.column) % 1792; + + DecodedAddress offsetAddress(decodedAddress); + offsetAddress.row = newRow; + offsetAddress.column = newColumn; + return offsetAddress; +} + +void EccModule::end_of_simulation() +{ + uint64_t latencies = 0; + uint64_t numberOfLatencies = 0; + + for (auto const &[latency, occurences] : latencyMap) + { + latencies += (latency.to_double() / 1000.0) * occurences; + numberOfLatencies += occurences; + } + + std::cout << "Average latency: " << static_cast(latencies) / numberOfLatencies << std::endl; +} + +sc_time EccModule::roundLatency(sc_time latency) +{ + static const sc_time BUCKET_SIZE = sc_time(1, SC_NS); + latency += BUCKET_SIZE / 2; + latency = latency - (latency % BUCKET_SIZE); + return latency; +} + +bool EccModule::activeEccBlock(Bank bank, Row row, Block block) const +{ + auto eccIt = std::find_if(activeEccBlocks.at(bank).cbegin(), activeEccBlocks.at(bank).cend(), + [block, row](EccIdentifier identifier) { + return (identifier.first == block) && (identifier.second == row); + }); + + return eccIt != activeEccBlocks.at(bank).cend(); +} diff --git a/src/simulator/simulator/EccModule.h b/src/simulator/simulator/EccModule.h new file mode 100644 index 00000000..15817db3 --- /dev/null +++ b/src/simulator/simulator/EccModule.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Christian Malek + * Derek Christ + */ + +#ifndef ECCMODULE_H +#define ECCMODULE_H + +#include "simulator/MemoryManager.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +class EccModule : public sc_core::sc_module +{ +public: + tlm_utils::simple_initiator_socket iSocket; + tlm_utils::simple_target_socket tSocket; + + EccModule(sc_core::sc_module_name name, AddressDecoder const &addressDecoder); + SC_HAS_PROCESS(EccModule); + +private: + using Block = uint64_t; + using Row = uint64_t; + using Bank = unsigned int; + using EccIdentifier = std::pair; + using EccQueue = std::deque; + + static DecodedAddress calculateOffsetAddress(DecodedAddress decodedAddress); + static sc_core::sc_time roundLatency(sc_core::sc_time latency); + bool activeEccBlock(Bank bank, Row row, Block block) const; + + void end_of_simulation() override; + + void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); + + tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &payload, + tlm::tlm_phase &phase, + sc_core::sc_time &fwDelay); + tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, + tlm::tlm_phase &phase, + sc_core::sc_time &bwDelay); + + tlm::tlm_generic_payload *generateEccPayload(DecodedAddress decodedAddress); + + static unsigned int alignToBlock(unsigned int column); + + tlm_utils::peq_with_cb_and_phase payloadEventQueue; + + tlm::tlm_generic_payload *pendingRequest = nullptr; + tlm::tlm_generic_payload *blockedRequest = nullptr; + bool targetBusy = false; + + const sc_core::sc_time tCK; + MemoryManager memoryManager; + AddressDecoder const &addressDecoder; + + std::unordered_map activeEccBlocks; + + using EccPayload = tlm::tlm_generic_payload *; + using StartTime = sc_core::sc_time; + std::unordered_map payloadMap; + + using Latency = sc_core::sc_time; + std::map latencyMap; +}; + +#endif // ECCMODULE_H diff --git a/src/simulator/simulator/Initiator.h b/src/simulator/simulator/Initiator.h new file mode 100644 index 00000000..817fb00e --- /dev/null +++ b/src/simulator/simulator/Initiator.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include + +class Initiator +{ +public: + virtual ~Initiator() = default; + + virtual void bind(tlm_utils::multi_target_base<> &target) = 0; + virtual uint64_t totalRequests() = 0; +}; diff --git a/src/simulator/simulator/SimpleInitiator.h b/src/simulator/simulator/SimpleInitiator.h new file mode 100644 index 00000000..3286ac5e --- /dev/null +++ b/src/simulator/simulator/SimpleInitiator.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include "Initiator.h" +#include "request/RequestIssuer.h" + +template +class SimpleInitiator : public Initiator +{ +public: + SimpleInitiator(sc_core::sc_module_name const &name, + MemoryManager &memoryManager, + std::optional maxPendingReadRequests, + std::optional maxPendingWriteRequests, + std::function transactionFinished, + std::function terminate, + Producer &&producer) + : producer(std::forward(producer)), + issuer( + name, + memoryManager, + maxPendingReadRequests, + maxPendingWriteRequests, + [this] { return this->producer.nextRequest(); }, + std::move(transactionFinished), + std::move(terminate)) + { + } + + void bind(tlm_utils::multi_target_base<> &target) override { issuer.iSocket.bind(target); } + uint64_t totalRequests() override { return producer.totalRequests(); }; + +private: + Producer producer; + RequestIssuer issuer; +}; diff --git a/src/simulator/simulator/StlPlayer.cpp b/src/simulator/simulator/StlPlayer.cpp deleted file mode 100644 index 967206c5..00000000 --- a/src/simulator/simulator/StlPlayer.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Éder F. Zulian - * Felipe S. Prado - * Derek Christ - */ - -#include "StlPlayer.h" - -using namespace sc_core; -using namespace tlm; - -StlPlayer::StlPlayer(const sc_module_name &name, const Configuration& config, const std::string &pathToTrace, - const sc_time &playerClk, unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, - TraceSetup& setup, bool relative) : - TrafficInitiator(name, config, setup, maxPendingReadRequests, maxPendingWriteRequests, - config.memSpec->defaultBytesPerBurst), - file(pathToTrace), relative(relative), playerClk(playerClk) -{ - currentBuffer = &lineContents[0]; - parseBuffer = &lineContents[1]; - - if (!file.is_open()) - SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str()); - else - { - std::string line; - while (std::getline(file, line)) - { - if (line.size() > 1 && line[0] != '#') - numberOfLines++; - } - file.clear(); - file.seekg(0); - - if (numberOfLines == 0) - SC_REPORT_FATAL("StlPlayer", "Trace file is empty"); - } - - currentBuffer->reserve(lineBufferSize); - parseBuffer->reserve(lineBufferSize); - - parseTraceFile(); - lineIterator = currentBuffer->cend(); -} - -StlPlayer::~StlPlayer() -{ - if (parserThread.joinable()) - parserThread.join(); -} - -void StlPlayer::sendNextPayload() -{ - if (lineIterator == currentBuffer->cend()) - { - lineIterator = swapBuffers(); - if (lineIterator == currentBuffer->cend()) - { - // The file is empty. Nothing more to do. - finished = true; - return; - } - } - - // Allocate a generic payload for this request. - tlm_generic_payload& payload = setup.allocatePayload(lineIterator->dataLength); - payload.acquire(); - - // Fill up the payload. - payload.set_address(lineIterator->address); - payload.set_response_status(TLM_INCOMPLETE_RESPONSE); - payload.set_dmi_allowed(false); - payload.set_byte_enable_length(0); - payload.set_data_length(lineIterator->dataLength); - payload.set_command(lineIterator->command); - std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload.get_data_ptr()); - - sc_time sendingTime; - sc_time sendingOffset; - - if (transactionsSent == 0) - sendingOffset = SC_ZERO_TIME; - else - sendingOffset = playerClk - (sc_time_stamp() % playerClk); - - if (!relative) - sendingTime = std::max(sc_time_stamp() + sendingOffset, lineIterator->sendingTime); - else - sendingTime = sc_time_stamp() + sendingOffset + lineIterator->sendingTime; - - sendToTarget(payload, BEGIN_REQ, sendingTime - sc_time_stamp()); - - transactionsSent++; - - if (payload.get_command() == tlm::TLM_READ_COMMAND) - pendingReadRequests++; - else if (payload.get_command() == tlm::TLM_WRITE_COMMAND) - pendingWriteRequests++; - - PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); - lineIterator++; -} - -void StlPlayer::parseTraceFile() -{ - unsigned parsedLines = 0; - parseBuffer->clear(); - while (file && !file.eof() && parsedLines < lineBufferSize) - { - // Get a new line from the input file. - std::string line; - std::getline(file, line); - lineCnt++; - - // If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is ignored. - if (line.size() <= 1 || line.at(0) == '#') - continue; - - parsedLines++; - parseBuffer->emplace_back(); - LineContent &content = parseBuffer->back(); - - // Trace files MUST provide timestamp, command and address for every - // transaction. The data information depends on the storage mode - // configuration. - std::string element; - std::istringstream iss; - - iss.str(line); - - // Get the timestamp for the transaction. - iss >> element; - if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); - content.sendingTime = playerClk * static_cast(std::stoull(element)); - - // Get the optional burst length and command - iss >> element; - if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); - if (element.at(0) == '(') - { - element.erase(0, 1); - content.dataLength = std::stoul(element); - iss >> element; - if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); - } - else - content.dataLength = defaultDataLength; - - if (element == "read") - content.command = TLM_READ_COMMAND; - else if (element == "write") - content.command = TLM_WRITE_COMMAND; - else - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); - - // Get the address. - iss >> element; - if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); - content.address = std::stoull(element, nullptr, 16); - - // Get the data if necessary. - if (storageEnabled && content.command == TLM_WRITE_COMMAND) - { - // The input trace file must provide the data to be stored into the memory. - iss >> element; - - // Check if data length in the trace file is correct. - // We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix. - if (element.length() != (content.dataLength * 2 + 2)) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); - - // Set data - for (unsigned i = 0; i < content.dataLength; i++) - content.data.emplace_back(static_cast - (std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16))); - } - } -} - -std::vector::const_iterator StlPlayer::swapBuffers() -{ - // Wait for parser to finish - if (parserThread.joinable()) - parserThread.join(); - - // Swap buffers - std::swap(currentBuffer, parseBuffer); - - // Start new parser thread - parserThread = std::thread(&StlPlayer::parseTraceFile, this); - - return currentBuffer->cbegin(); -} - -uint64_t StlPlayer::getNumberOfLines() const -{ - return numberOfLines; -} diff --git a/src/simulator/simulator/TraceSetup.cpp b/src/simulator/simulator/TraceSetup.cpp deleted file mode 100644 index 2af57f0a..00000000 --- a/src/simulator/simulator/TraceSetup.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2017, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Matthias Jung - * Luiza Correa - * Derek Christ - */ - -#include "TraceSetup.h" - -#include "simulator/StlPlayer.h" -#include "simulator/TrafficGenerator.h" - -#include -#include -#include - -using namespace sc_core; -using namespace tlm; - -TraceSetup::TraceSetup(const Configuration& config, - const DRAMSys::Config::TraceSetup& traceSetup, - const std::string& pathToResources, - std::vector>& players) - : memoryManager(config.storeMode != Configuration::StoreMode::NoStorage) -{ - if (traceSetup.initiators.empty()) - SC_REPORT_FATAL("TraceSetup", "No traffic initiators specified"); - - for (const auto &initiator : traceSetup.initiators) - { - std::visit( - [&](auto &&initiator) - { - std::string name = initiator.name; - double frequencyMHz = initiator.clkMhz; - sc_time playerClk = sc_time(1.0 / frequencyMHz, SC_US); - - unsigned int maxPendingReadRequests = [=]() -> unsigned int - { - if (const auto &maxPendingReadRequests = initiator.maxPendingReadRequests) - return *maxPendingReadRequests; - else - return 0; - }(); - - unsigned int maxPendingWriteRequests = [=]() -> unsigned int - { - if (const auto &maxPendingWriteRequests = initiator.maxPendingWriteRequests) - return *maxPendingWriteRequests; - else - return 0; - }(); - - using T = std::decay_t; - if constexpr (std::is_same_v) - { - size_t pos = name.rfind('.'); - if (pos == std::string::npos) - throw std::runtime_error("Name of the trace file does not contain a valid extension."); - - // Get the extension and make it lower case - std::string ext = name.substr(pos + 1); - std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); - - std::stringstream stlFileStream; - stlFileStream << pathToResources << "/traces/" << name; - std::string stlFile = stlFileStream.str(); - std::string moduleName = name; - - // replace all '.' to '_' - std::replace(moduleName.begin(), moduleName.end(), '.', '_'); - - StlPlayer *player; - if (ext == "stl") - player = new StlPlayer(moduleName.c_str(), config, stlFile, playerClk, maxPendingReadRequests, - maxPendingWriteRequests, *this, false); - else if (ext == "rstl") - player = new StlPlayer(moduleName.c_str(), config, stlFile, playerClk, maxPendingReadRequests, - maxPendingWriteRequests, *this, true); - else - throw std::runtime_error("Unsupported file extension in " + name); - - players.push_back(std::unique_ptr(player)); - totalTransactions += player->getNumberOfLines(); - } - else if constexpr (std::is_same_v) - { - auto* trafficGenerator = new TrafficGenerator(name.c_str(), config, initiator, *this); - players.push_back(std::unique_ptr(trafficGenerator)); - - totalTransactions += trafficGenerator->getTotalTransactions(); - } - else // if constexpr (std::is_same_v) - { - uint64_t numRequests = initiator.numRequests; - uint64_t rowIncrement = initiator.rowIncrement; - - players.push_back( - std::unique_ptr(new TrafficGeneratorHammer(name.c_str(), config, initiator, *this))); - totalTransactions += numRequests; - } - }, - initiator); - } - - for (const auto &inititatorConf : traceSetup.initiators) - { - if (auto generatorConf = std::get_if(&inititatorConf)) - { - if (const auto &idleUntil = generatorConf->idleUntil) - { - const std::string name = generatorConf->name; - auto listenerIt = std::find_if(players.begin(), players.end(), - [&name](const std::unique_ptr &initiator) - { return initiator->name() == name; }); - - // Should be found - auto listener = dynamic_cast(listenerIt->get()); - - auto notifierIt = - std::find_if(players.begin(), players.end(), - [&idleUntil](const std::unique_ptr &initiator) - { - if (auto generator = dynamic_cast(initiator.get())) - { - if (generator->hasStateTransitionEvent(*idleUntil)) - return true; - } - - return false; - }); - - if (notifierIt == players.end()) - SC_REPORT_FATAL("TraceSetup", "Event to listen on not found."); - - auto notifier = dynamic_cast(notifierIt->get()); - listener->waitUntil(¬ifier->getStateTransitionEvent(*idleUntil)); - } - } - } - - remainingTransactions = totalTransactions; - numberOfTrafficInitiators = players.size(); - defaultDataLength = config.memSpec->defaultBytesPerBurst; -} - -void TraceSetup::trafficInitiatorTerminates() -{ - finishedTrafficInitiators++; - - if (finishedTrafficInitiators == numberOfTrafficInitiators) - sc_stop(); -} - -void TraceSetup::transactionFinished() -{ - remainingTransactions--; - - loadBar(totalTransactions - remainingTransactions, totalTransactions); - - if (remainingTransactions == 0) - std::cout << std::endl; -} - -tlm_generic_payload& TraceSetup::allocatePayload(unsigned dataLength) -{ - return memoryManager.allocate(dataLength); -} - -tlm_generic_payload& TraceSetup::allocatePayload() -{ - return allocatePayload(defaultDataLength); -} - -void TraceSetup::loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity) -{ - if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0))) - return; - - float ratio = x / (float)n; - unsigned int c = (ratio * w); - float rest = (ratio * w) - c; - std::cout << std::setw(3) << round(ratio * 100) << "% |"; - for (unsigned int x = 0; x < c; x++) - std::cout << "█"; - - if (rest >= 0 && rest < 0.125f && c != w) - std::cout << " "; - if (rest >= 0.125f && rest < 2 * 0.125f) - std::cout << "▏"; - if (rest >= 2 * 0.125f && rest < 3 * 0.125f) - std::cout << "▎"; - if (rest >= 3 * 0.125f && rest < 4 * 0.125f) - std::cout << "▍"; - if (rest >= 4 * 0.125f && rest < 5 * 0.125f) - std::cout << "▌"; - if (rest >= 5 * 0.125f && rest < 6 * 0.125f) - std::cout << "▋"; - if (rest >= 6 * 0.125f && rest < 7 * 0.125f) - std::cout << "▊"; - if (rest >= 7 * 0.125f && rest < 8 * 0.125f) - std::cout << "▉"; - - for (unsigned int x = c; x < (w - 1); x++) - std::cout << " "; - std::cout << "|\r" << std::flush; -} diff --git a/src/simulator/simulator/TrafficGenerator.cpp b/src/simulator/simulator/TrafficGenerator.cpp deleted file mode 100644 index abcc5878..00000000 --- a/src/simulator/simulator/TrafficGenerator.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Derek Christ - */ - -#include "TrafficGenerator.h" - -#include "simulator/TraceSetup.h" - -#include - -using namespace sc_core; -using namespace tlm; - -TrafficGeneratorIf::TrafficGeneratorIf(const sc_core::sc_module_name& name, const Configuration& config, - TraceSetup& setup, - unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, - unsigned int dataLength) - : TrafficInitiator(name, config, setup, maxPendingReadRequests, maxPendingWriteRequests, dataLength) -{ -} - -void TrafficGeneratorIf::sendNextPayload() -{ - prepareNextPayload(); - - if (finished) - return; - - // TODO: column / burst breite - - uint64_t address = getNextAddress(); - - tlm_command command = getNextCommand(); - - if (command == tlm::TLM_READ_COMMAND) - pendingReadRequests++; - else if (command == tlm::TLM_WRITE_COMMAND) - pendingWriteRequests++; - - tlm_generic_payload& payload = setup.allocatePayload(); - payload.acquire(); - payload.set_address(address); - payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); - payload.set_dmi_allowed(false); - payload.set_byte_enable_length(0); - payload.set_data_length(defaultDataLength); - payload.set_command(command); - - sc_time generatorClk = getGeneratorClk(); - sc_time sendingOffset; - if (transactionsSent == 0) - sendingOffset = SC_ZERO_TIME + generatorClk * clksToIdle(); - else - sendingOffset = (generatorClk * clksPerRequest()) - (sc_time_stamp() % generatorClk) + generatorClk * clksToIdle(); - - // TODO: do not send two requests in the same cycle - sendToTarget(payload, tlm::BEGIN_REQ, sendingOffset); - - transactionsSent++; - PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); - payloadSent(); -} - -TrafficGenerator::TrafficGenerator(const sc_module_name& name, const Configuration& config, - const DRAMSys::Config::TraceGenerator& conf, TraceSetup& setup) - : TrafficGeneratorIf(name, config, setup, conf.maxPendingReadRequests.value_or(defaultMaxPendingReadRequests), - conf.maxPendingWriteRequests.value_or(defaultMaxPendingWriteRequests), - conf.dataLength.value_or(config.memSpec->defaultBytesPerBurst)), - generatorClk(TrafficInitiator::evaluateGeneratorClk(conf)), conf(conf), - maxTransactions(conf.maxTransactions.value_or(std::numeric_limits::max())), - simMemSizeInBytes(config.memSpec->getSimMemSizeInBytes()), - randomGenerator(std::default_random_engine(conf.seed.value_or(defaultSeed))) -{ - // Perform checks for all states - for (const auto &state : conf.states) - { - if (auto trafficState = std::get_if(&state.second)) - { - uint64_t minAddress = evaluateMinAddress(*trafficState); - uint64_t maxAddress = evaluateMaxAddress(*trafficState, simMemSizeInBytes); - double rwRatio = (*trafficState).rwRatio; - - if (minAddress > config.memSpec->getSimMemSizeInBytes() - 1) - SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); - - if (maxAddress > config.memSpec->getSimMemSizeInBytes() - 1) - SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); - - if (maxAddress < minAddress) - SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress."); - - if (rwRatio < 0 || rwRatio > 1) - SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1."); - - if (const auto &eventName = trafficState->notify) - { - stateTranstitionEvents.emplace(std::piecewise_construct, std::forward_as_tuple(*eventName), - std::forward_as_tuple(eventName->c_str(), state.first)); - } - } - } - - if (auto trafficState = - std::get_if(&conf.states.at(currentState))) - { - uint64_t minAddress = evaluateMinAddress(*trafficState); - uint64_t maxAddress = evaluateMaxAddress(*trafficState, simMemSizeInBytes); - randomAddressDistribution = std::uniform_int_distribution(minAddress, maxAddress); - currentClksPerRequest = trafficState->clksPerRequest.value_or(defaultClksPerRequest); - } - - calculateTransitions(); -} - -void TrafficGenerator::calculateTransitions() -{ - unsigned int state = 0; - uint64_t totalTransactions = 0; - stateSequence.push_back(state); - - while (true) - { - auto transitionsIt = conf.transitions.equal_range(state); - float probabilityAccumulated = 0.0f; - std::map> transitionsDistribution; - - for (auto it = transitionsIt.first; it != transitionsIt.second; ++it) - { - float lowerLimit = probabilityAccumulated; - probabilityAccumulated += it->second.probability; - float upperLimit = probabilityAccumulated; - transitionsDistribution[it->second.to] = {lowerLimit, upperLimit}; - } - - if (probabilityAccumulated > 1.001f) - SC_REPORT_WARNING("TrafficGenerator", "Sum of transition probabilities greater than 1."); - - float random = randomDistribution(randomGenerator); - bool transitionFound = false; - - for (const auto &transition : transitionsDistribution) - { - auto to = transition.first; - auto limits = transition.second; - - if (limits.first < random && limits.second > random) - { - state = to; - stateSequence.push_back(state); - transitionFound = true; - break; - } - } - - if (transitionFound) - { - if (auto trafficState = - std::get_if(&conf.states.at(state))) - totalTransactions += trafficState->numRequests; - - if (totalTransactions < maxTransactions) - continue; - } - - break; - } - - stateIt = stateSequence.cbegin(); -} - -bool TrafficGenerator::hasStateTransitionEvent(const std::string &eventName) const -{ - auto it = stateTranstitionEvents.find(eventName); - - if (it == stateTranstitionEvents.end()) - return false; - - return true; -} - -const sc_core::sc_event &TrafficGenerator::getStateTransitionEvent(const std::string &eventName) const -{ - auto it = stateTranstitionEvents.find(eventName); - - if (it == stateTranstitionEvents.end()) - SC_REPORT_FATAL("TraceSetup", "StateTransitionEvent not found."); - - return it->second.event; -} - -uint64_t TrafficGenerator::getTotalTransactions() const -{ - uint64_t totalTransactions = 0; - - for (auto state : stateSequence) - { - if (auto trafficState = std::get_if(&conf.states.at(state))) - totalTransactions += trafficState->numRequests; - } - - if (totalTransactions > maxTransactions) - totalTransactions = maxTransactions; - - return totalTransactions; -} - -void TrafficGenerator::waitUntil(const sc_core::sc_event *ev) -{ - startEvent = ev; -} - -void TrafficGenerator::transitionToNextState() -{ - ++stateIt; - - if (stateIt == stateSequence.cend() || transactionsSent >= maxTransactions) - { - // No transition performed. - finished = true; - return; - } - - currentState = *stateIt; - - // Notify - for (auto &it : stateTranstitionEvents) - { - if (it.second.stateId == currentState) - it.second.event.notify(); - } - - if (auto idleState = std::get_if(&conf.states.at(currentState))) - { - currentClksToIdle += idleState->idleClks; - transitionToNextState(); - return; - } - else if (auto trafficState = - std::get_if(&conf.states.at(currentState))) - { - uint64_t minAddress = evaluateMinAddress(*trafficState); - uint64_t maxAddress = evaluateMaxAddress(*trafficState, simMemSizeInBytes); - randomAddressDistribution = std::uniform_int_distribution(minAddress, maxAddress); - currentClksPerRequest = trafficState->clksPerRequest.value_or(defaultClksPerRequest); - } - - currentAddress = 0x00; - transactionsSentInCurrentState = 0; -} - -void TrafficGenerator::prepareNextPayload() -{ - if (transactionsSent >= maxTransactions) - { - finished = true; - return; - } - - if (startEvent && transactionsSent == 0) - wait(*startEvent); - - if (auto trafficState = - std::get_if(&conf.states.at(currentState))) - { - if (transactionsSentInCurrentState >= trafficState->numRequests) - transitionToNextState(); - } - - // In case we are in an idle state right at the beginning of the simulation, - // set the clksToIdle and transition to the next state. - if (auto idleState = - std::get_if(&conf.states.at(currentState))) - { - currentClksToIdle = idleState->idleClks; - transitionToNextState(); - } -} - -void TrafficGenerator::payloadSent() -{ - // Reset clks to idle. - currentClksToIdle = 0; - - transactionsSentInCurrentState++; -} - -tlm::tlm_command TrafficGenerator::getNextCommand() -{ - // An idle state should never reach this method. - auto &state = std::get(conf.states.at(currentState)); - - tlm_command command; - if (randomDistribution(randomGenerator) < state.rwRatio) - command = tlm::TLM_READ_COMMAND; - else - command = tlm::TLM_WRITE_COMMAND; - - return command; -} - -sc_core::sc_time TrafficGenerator::getGeneratorClk() const -{ - return generatorClk; -} - -uint64_t TrafficGenerator::getNextAddress() -{ - using DRAMSys::Config::AddressDistribution; - - // An idle state should never reach this method. - auto &state = std::get(conf.states.at(currentState)); - - uint64_t minAddress = evaluateMinAddress(state); - uint64_t maxAddress = evaluateMaxAddress(state, simMemSizeInBytes); - - if (state.addressDistribution == AddressDistribution::Sequential) - { - uint64_t addressIncrement = state.addressIncrement.value_or(defaultAddressIncrement); - - uint64_t address = currentAddress; - currentAddress += addressIncrement; - if (currentAddress > maxAddress) - currentAddress = minAddress; - return address; - } - else if (state.addressDistribution == AddressDistribution::Random) - { - return randomAddressDistribution(randomGenerator); - } - else - { - return 0x00; - } -} - -uint64_t TrafficGenerator::evaluateMinAddress(const DRAMSys::Config::TraceGeneratorTrafficState &state) -{ - return state.minAddress.value_or(0x00); -} - -uint64_t TrafficGenerator::evaluateMaxAddress(const DRAMSys::Config::TraceGeneratorTrafficState &state, - uint64_t simMemSizeInBytes) -{ - return state.maxAddress.value_or(simMemSizeInBytes - 1); -} - -TrafficGeneratorHammer::TrafficGeneratorHammer(const sc_core::sc_module_name &name, const Configuration& config, - const DRAMSys::Config::TraceHammer &conf, TraceSetup& setup) - : TrafficGeneratorIf(name, config, setup, 1, 1, config.memSpec->defaultBytesPerBurst), - generatorClk(evaluateGeneratorClk(conf)), rowIncrement(conf.rowIncrement), numRequests(conf.numRequests) -{ -} - -tlm::tlm_command TrafficGeneratorHammer::getNextCommand() -{ - return tlm::TLM_READ_COMMAND; -} - -sc_core::sc_time TrafficGeneratorHammer::getGeneratorClk() const -{ - return generatorClk; -} - -uint64_t TrafficGeneratorHammer::getNextAddress() -{ - if (currentAddress == 0x0) - currentAddress = rowIncrement; - else - currentAddress = 0x0; - - return currentAddress; -} - -void TrafficGeneratorHammer::prepareNextPayload() -{ - if (transactionsSent >= numRequests) - finished = true; -} diff --git a/src/simulator/simulator/TrafficGenerator.h b/src/simulator/simulator/TrafficGenerator.h deleted file mode 100644 index 7732fa9d..00000000 --- a/src/simulator/simulator/TrafficGenerator.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - * Derek Christ - */ - -#ifndef TRAFFICGENERATOR_H -#define TRAFFICGENERATOR_H - -#include "simulator/TrafficInitiator.h" -#include "simulator/TraceSetup.h" - -#include -#include -#include - -class TrafficGeneratorIf : public TrafficInitiator -{ -public: - TrafficGeneratorIf(const sc_core::sc_module_name &name, const Configuration& config, TraceSetup& setup, - unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, - unsigned int dataLength); - -private: - void sendNextPayload() override; - virtual void prepareNextPayload(){}; - virtual uint64_t getNextAddress() = 0; - virtual tlm::tlm_command getNextCommand() = 0; - virtual sc_core::sc_time getGeneratorClk() const = 0; - virtual void payloadSent(){}; - virtual uint64_t clksPerRequest() const { return 1; } - virtual uint64_t clksToIdle() const { return 0; } -}; - -class TrafficGenerator : public TrafficGeneratorIf -{ -public: - TrafficGenerator(const sc_core::sc_module_name &name, const Configuration& config, - const DRAMSys::Config::TraceGenerator &conf, TraceSetup& setup); - - uint64_t getTotalTransactions() const; - void waitUntil(const sc_core::sc_event *ev); - bool hasStateTransitionEvent(const std::string &eventName) const; - const sc_core::sc_event &getStateTransitionEvent(const std::string &eventName) const; - -private: - static uint64_t evaluateMinAddress(const DRAMSys::Config::TraceGeneratorTrafficState& state); - static uint64_t evaluateMaxAddress(const DRAMSys::Config::TraceGeneratorTrafficState& state, - uint64_t simMemSizeInBytes); - - void prepareNextPayload() override; - uint64_t getNextAddress() override; - tlm::tlm_command getNextCommand() override; - sc_core::sc_time getGeneratorClk() const override; - void payloadSent() override; - uint64_t clksPerRequest() const override { return currentClksPerRequest; }; - uint64_t clksToIdle() const override { return currentClksToIdle; } - - void calculateTransitions(); - void transitionToNextState(); - - sc_core::sc_time generatorClk; - - const DRAMSys::Config::TraceGenerator &conf; - unsigned int currentState = 0; - uint64_t currentAddress = 0x00; - uint64_t currentClksPerRequest = 1; - uint64_t transactionsSentInCurrentState = 0; - - const uint64_t maxTransactions; - const uint64_t simMemSizeInBytes; - - uint64_t currentClksToIdle = 0; - - std::vector stateSequence; - std::vector::const_iterator stateIt; - - struct EventPair - { - EventPair(const std::string &name, unsigned int id) : event(name.c_str()), stateId(id) - { - } - sc_core::sc_event event; - unsigned int stateId; - }; - std::map stateTranstitionEvents; - - bool idleAtStart = false; - const sc_core::sc_event *startEvent = nullptr; - - std::default_random_engine randomGenerator; - std::uniform_real_distribution randomDistribution = std::uniform_real_distribution(0.0f, 1.0f); - std::uniform_int_distribution randomAddressDistribution; - - static constexpr uint64_t defaultSeed = 0; - static constexpr uint64_t defaultClksPerRequest = 1; - static constexpr uint64_t defaultAddressIncrement = 0x00; -}; - -class TrafficGeneratorHammer final : public TrafficGeneratorIf -{ -public: - TrafficGeneratorHammer(const sc_core::sc_module_name &name, const Configuration& config, - const DRAMSys::Config::TraceHammer &conf, TraceSetup& setup); - -private: - void prepareNextPayload() override; - uint64_t getNextAddress() override; - tlm::tlm_command getNextCommand() override; - sc_core::sc_time getGeneratorClk() const override; - - sc_core::sc_time generatorClk; - uint64_t rowIncrement; - uint64_t currentAddress = 0x0; - uint64_t numRequests; -}; - -#endif // TRAFFICGENERATOR_H diff --git a/src/simulator/simulator/TrafficInitiator.cpp b/src/simulator/simulator/TrafficInitiator.cpp deleted file mode 100644 index 70c4eeae..00000000 --- a/src/simulator/simulator/TrafficInitiator.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Éder F. Zulian - * Felipe S. Prado - * Derek Christ - */ - -#include "TrafficInitiator.h" - -using namespace sc_core; -using namespace tlm; - -TrafficInitiator::TrafficInitiator(const sc_module_name &name, const Configuration& config, TraceSetup& setup, - unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, unsigned int defaultDataLength) : - sc_module(name), - payloadEventQueue(this, &TrafficInitiator::peqCallback), - setup(setup), - maxPendingReadRequests(maxPendingReadRequests), - maxPendingWriteRequests(maxPendingWriteRequests), - defaultDataLength(defaultDataLength), - storageEnabled(config.storeMode != Configuration::StoreMode::NoStorage), - simulationProgressBar(config.simulationProgressBar) -{ - SC_THREAD(sendNextPayload); - iSocket.register_nb_transport_bw(this, &TrafficInitiator::nb_transport_bw); -} - -void TrafficInitiator::terminate() -{ - std::cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl; - setup.trafficInitiatorTerminates(); -} - -tlm_sync_enum TrafficInitiator::nb_transport_bw(tlm_generic_payload &payload, - tlm_phase &phase, sc_time &bwDelay) -{ - payloadEventQueue.notify(payload, phase, bwDelay); - return TLM_ACCEPTED; -} - -void TrafficInitiator::peqCallback(tlm_generic_payload &payload, - const tlm_phase &phase) -{ - if (phase == END_REQ) - { - if (nextPayloadSendable()) - sendNextPayload(); - else - payloadPostponed = true; - } - else if (phase == BEGIN_RESP) - { - payload.release(); - sendToTarget(payload, END_RESP, SC_ZERO_TIME); - if (simulationProgressBar) - setup.transactionFinished(); - - transactionsReceived++; - - if (payload.get_command() == tlm::TLM_READ_COMMAND) - pendingReadRequests--; - else if (payload.get_command() == tlm::TLM_WRITE_COMMAND) - pendingWriteRequests--; - - // If the initiator wasn't able to send the next payload in the END_REQ phase, do it now. - if (payloadPostponed && nextPayloadSendable()) - { - sendNextPayload(); - payloadPostponed = false; - } - - // If all answers were received: - if (finished && transactionsSent == transactionsReceived) - terminate(); - } - else - { - SC_REPORT_FATAL("TrafficInitiator", "PEQ was triggered with unknown phase"); - } -} - -void TrafficInitiator::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay) -{ - tlm_phase TPhase = phase; - sc_time TDelay = delay; - iSocket->nb_transport_fw(payload, TPhase, TDelay); -} - -bool TrafficInitiator::nextPayloadSendable() const -{ - // If either the maxPendingReadRequests or maxPendingWriteRequests - // limit is reached, do not send next payload. - if (((pendingReadRequests >= maxPendingReadRequests) && (maxPendingReadRequests != 0)) - || ((pendingWriteRequests >= maxPendingWriteRequests) && (maxPendingWriteRequests != 0))) - return false; - else - return true; -} - -sc_core::sc_time TrafficInitiator::evaluateGeneratorClk(const DRAMSys::Config::TrafficInitiator& conf) -{ - double frequencyMHz = conf.clkMhz; - sc_time playerClk = sc_time(1.0 / frequencyMHz, SC_US); - return playerClk; -} - diff --git a/src/simulator/simulator/generator/RandomProducer.cpp b/src/simulator/simulator/generator/RandomProducer.cpp new file mode 100644 index 00000000..418f3f68 --- /dev/null +++ b/src/simulator/simulator/generator/RandomProducer.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "RandomProducer.h" +#include "definitions.h" + +RandomProducer::RandomProducer(uint64_t numRequests, + std::optional seed, + double rwRatio, + unsigned int clkMhz, + std::optional minAddress, + std::optional maxAddress, + uint64_t memorySize, + unsigned int dataLength, + unsigned int dataAlignment) + : numberOfRequests(numRequests), + seed(seed.value_or(DEFAULT_SEED)), + rwRatio(rwRatio), + randomGenerator(this->seed), + generatorPeriod(sc_core::sc_time(1.0 / static_cast(clkMhz), sc_core::SC_US)), + dataLength(dataLength), + dataAlignment(dataAlignment), + randomAddressDistribution(minAddress.value_or(DEFAULT_MIN_ADDRESS), + maxAddress.value_or((memorySize) - dataLength)) +{ + if (minAddress > memorySize - 1) + SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); + + if (maxAddress > memorySize - 1) + SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); + + if (maxAddress < minAddress) + SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress."); + + if (rwRatio < 0 || rwRatio > 1) + SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1."); +} + +Request RandomProducer::nextRequest() +{ + Request request; + request.address = randomAddressDistribution(randomGenerator); + + // Align address + request.address = request.address - (request.address % dataAlignment); + + request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read + : Request::Command::Write; + request.length = dataLength; + request.delay = generatorPeriod; + + return request; +} diff --git a/src/simulator/simulator/generator/RandomProducer.h b/src/simulator/simulator/generator/RandomProducer.h new file mode 100644 index 00000000..1da6af9b --- /dev/null +++ b/src/simulator/simulator/generator/RandomProducer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include "simulator/request/RequestProducer.h" + +#include +#include + +class RandomProducer : public RequestProducer +{ +public: + RandomProducer(uint64_t numRequests, + std::optional seed, + double rwRatio, + unsigned int clkMhz, + std::optional minAddress, + std::optional maxAddress, + uint64_t memorySize, + unsigned int dataLength, + unsigned int dataAlignment); + + Request nextRequest() override; + + uint64_t totalRequests() override { return numberOfRequests; } + sc_core::sc_time clkPeriod() override { return generatorPeriod; } + + const uint64_t numberOfRequests; + const uint64_t seed; + const double rwRatio; + const sc_core::sc_time generatorPeriod; + const unsigned int dataLength; + const unsigned int dataAlignment; + + std::default_random_engine randomGenerator; + std::uniform_real_distribution readWriteDistribution{0.0, 1.0}; + std::uniform_int_distribution randomAddressDistribution; +}; diff --git a/src/simulator/simulator/generator/SequentialProducer.cpp b/src/simulator/simulator/generator/SequentialProducer.cpp new file mode 100644 index 00000000..1ca441fd --- /dev/null +++ b/src/simulator/simulator/generator/SequentialProducer.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "SequentialProducer.h" +#include "definitions.h" + +SequentialProducer::SequentialProducer(uint64_t numRequests, + std::optional seed, + double rwRatio, + unsigned int clkMhz, + std::optional addressIncrement, + std::optional minAddress, + std::optional maxAddress, + uint64_t memorySize, + unsigned int dataLength) + : numberOfRequests(numRequests), + addressIncrement(addressIncrement.value_or(dataLength)), + minAddress(minAddress.value_or(DEFAULT_MIN_ADDRESS)), + maxAddress(maxAddress.value_or(memorySize - 1)), + seed(seed.value_or(DEFAULT_SEED)), + rwRatio(rwRatio), + randomGenerator(this->seed), + generatorPeriod(sc_core::sc_time(1.0 / static_cast(clkMhz), sc_core::SC_US)), + dataLength(dataLength) +{ + if (minAddress > memorySize - 1) + SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); + + if (maxAddress > memorySize - 1) + SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); + + if (maxAddress < minAddress) + SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress."); + + if (rwRatio < 0 || rwRatio > 1) + SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1."); +} + +Request SequentialProducer::nextRequest() +{ + Request request; + request.address = generatedRequests * addressIncrement % (maxAddress - minAddress) + minAddress; + request.command = readWriteDistribution(randomGenerator) < rwRatio ? Request::Command::Read + : Request::Command::Write; + request.length = dataLength; + request.delay = generatorPeriod; + + generatedRequests++; + return request; +} diff --git a/src/simulator/simulator/generator/SequentialProducer.h b/src/simulator/simulator/generator/SequentialProducer.h new file mode 100644 index 00000000..01f6fd6f --- /dev/null +++ b/src/simulator/simulator/generator/SequentialProducer.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include "simulator/request/RequestProducer.h" + +#include +#include + +class SequentialProducer : public RequestProducer +{ +public: + SequentialProducer(uint64_t numRequests, + std::optional seed, + double rwRatio, + unsigned int clkMhz, + std::optional addressIncrement, + std::optional minAddress, + std::optional maxAddress, + uint64_t memorySize, + unsigned int dataLength); + + Request nextRequest() override; + + uint64_t totalRequests() override { return numberOfRequests; } + sc_core::sc_time clkPeriod() override { return generatorPeriod; } + void reset() override { generatedRequests = 0; } + + const uint64_t numberOfRequests; + const uint64_t addressIncrement; + const uint64_t minAddress; + const uint64_t maxAddress; + const uint64_t seed; + const double rwRatio; + const sc_core::sc_time generatorPeriod; + const unsigned int dataLength; + + std::default_random_engine randomGenerator; + std::uniform_real_distribution readWriteDistribution{0.0, 1.0}; + + uint64_t generatedRequests = 0; +}; diff --git a/src/simulator/simulator/generator/TrafficGenerator.cpp b/src/simulator/simulator/generator/TrafficGenerator.cpp new file mode 100644 index 00000000..ac588b63 --- /dev/null +++ b/src/simulator/simulator/generator/TrafficGenerator.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "TrafficGenerator.h" + +TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const &config, + MemoryManager &memoryManager, + uint64_t memorySize, + unsigned int defaultDataLength, + std::function transactionFinished, + std::function terminateInitiator) + : consumer( + config.name.c_str(), + memoryManager, + config.maxPendingReadRequests, + config.maxPendingWriteRequests, + [this] { return nextRequest(); }, + std::move(transactionFinished), + std::move(terminateInitiator)), + stateTransistions(config.transitions) +{ + unsigned int dataLength = config.dataLength.value_or(defaultDataLength); + unsigned int dataAlignment = config.dataAlignment.value_or(dataLength); + + for (auto const &state : config.states) + { + std::visit( + [=, &config](auto &&arg) + { + using DRAMSys::Config::TrafficGeneratorActiveState; + using DRAMSys::Config::TrafficGeneratorIdleState; + using T = std::decay_t; + if constexpr (std::is_same_v) + { + auto const &activeState = arg; + if (activeState.addressDistribution == + DRAMSys::Config::AddressDistribution::Random) + { + auto producer = std::make_unique(activeState.numRequests, + config.seed, + activeState.rwRatio, + config.clkMhz, + activeState.minAddress, + activeState.maxAddress, + memorySize, + dataLength, + dataAlignment); + + producers.emplace(activeState.id, std::move(producer)); + } + else + { + auto producer = + std::make_unique(activeState.numRequests, + config.seed, + activeState.rwRatio, + config.clkMhz, + activeState.addressIncrement, + activeState.minAddress, + activeState.maxAddress, + memorySize, + dataLength); + + producers.emplace(activeState.id, std::move(producer)); + } + } + else if constexpr (std::is_same_v) + { + auto const &idleState = arg; + idleStateClks.emplace(idleState.id, idleState.idleClks); + } + }, + state); + } +} + +TrafficGenerator::TrafficGenerator(DRAMSys::Config::TrafficGenerator const &config, + MemoryManager &memoryManager, + uint64_t memorySize, + unsigned int defaultDataLength, + std::function transactionFinished, + std::function terminateInitiator) + : consumer( + config.name.c_str(), + memoryManager, + config.maxPendingReadRequests, + config.maxPendingWriteRequests, + [this] { return nextRequest(); }, + std::move(transactionFinished), + std::move(terminateInitiator)) +{ + unsigned int dataLength = config.dataLength.value_or(defaultDataLength); + unsigned int dataAlignment = config.dataAlignment.value_or(dataLength); + + if (config.addressDistribution == DRAMSys::Config::AddressDistribution::Random) + { + auto producer = std::make_unique(config.numRequests, + config.seed, + config.rwRatio, + config.clkMhz, + config.minAddress, + config.maxAddress, + memorySize, + dataLength, + dataAlignment); + producers.emplace(0, std::move(producer)); + } + else + { + auto producer = std::make_unique(config.numRequests, + config.seed, + config.rwRatio, + config.clkMhz, + config.addressIncrement, + config.minAddress, + config.maxAddress, + memorySize, + dataLength); + producers.emplace(0, std::move(producer)); + } +} + +Request TrafficGenerator::nextRequest() +{ + uint64_t clksToIdle = 0; + if (requestsInState >= producers[currentState]->totalRequests()) + { + // Reset current producer to its initial state + producers[currentState]->reset(); + + auto newState = stateTransition(currentState); + + if (!newState.has_value()) + return Request{.command = Request::Command::Stop}; + + auto idleStateIt = idleStateClks.find(newState.value()); + while (idleStateIt != idleStateClks.cend()) + { + clksToIdle += idleStateIt->second; + newState = stateTransition(currentState); + + if (!newState.has_value()) + return Request{.command = Request::Command::Stop}; + + currentState = newState.value(); + idleStateIt = idleStateClks.find(newState.value()); + } + + currentState = newState.value(); + requestsInState = 0; + } + + requestsInState++; + + Request request = producers[currentState]->nextRequest(); + request.delay += producers[currentState]->clkPeriod() * clksToIdle; + return request; +} + +uint64_t TrafficGenerator::totalRequests() +{ + // Store current state of random generator + std::default_random_engine tempGenerator(randomGenerator); + + // Reset generator to initial state + randomGenerator.seed(); + + uint64_t totalRequests = 0; + unsigned int currentState = 0; + + if (producers.find(currentState) != producers.cend()) + totalRequests += producers.at(currentState)->totalRequests(); + + while (auto nextState = stateTransition(currentState)) + { + currentState = nextState.value(); + + if (producers.find(currentState) != producers.cend()) + totalRequests += producers.at(currentState)->totalRequests(); + } + + // Restore state of random generator + randomGenerator = tempGenerator; + + return totalRequests; +} + +std::optional TrafficGenerator::stateTransition(unsigned int from) +{ + using Transition = DRAMSys::Config::TrafficGeneratorStateTransition; + + std::vector relevantTransitions; + std::copy_if(stateTransistions.cbegin(), + stateTransistions.cend(), + std::back_inserter(relevantTransitions), + [from](Transition transition) { return transition.from == from; }); + + if (relevantTransitions.empty()) + return std::nullopt; + + std::vector propabilities; + std::for_each(relevantTransitions.cbegin(), + relevantTransitions.cend(), + [&propabilities](Transition transition) + { propabilities.push_back(transition.probability); }); + + assert(propabilities.size() == relevantTransitions.size()); + + std::discrete_distribution stateTransitionDistribution(propabilities.cbegin(), + propabilities.cend()); + + std::size_t index = stateTransitionDistribution(randomGenerator); + return relevantTransitions[index].to; +} diff --git a/src/simulator/simulator/generator/TrafficGenerator.h b/src/simulator/simulator/generator/TrafficGenerator.h new file mode 100644 index 00000000..b7c92b93 --- /dev/null +++ b/src/simulator/simulator/generator/TrafficGenerator.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include "RandomProducer.h" +#include "SequentialProducer.h" +#include "simulator/Initiator.h" +#include "simulator/MemoryManager.h" +#include "simulator/request/RequestIssuer.h" + +#include + +class TrafficGenerator : public Initiator +{ +public: + TrafficGenerator(DRAMSys::Config::TrafficGenerator const &config, + MemoryManager &memoryManager, + uint64_t memorySize, + unsigned int defaultDataLength, + std::function transactionFinished, + std::function terminateInitiator); + + TrafficGenerator(DRAMSys::Config::TrafficGeneratorStateMachine const &config, + MemoryManager &memoryManager, + uint64_t memorySize, + unsigned int defaultDataLength, + std::function transactionFinished, + std::function terminateInitiator); + + void bind(tlm_utils::multi_target_base<> &target) override { consumer.iSocket.bind(target); } + + uint64_t totalRequests() override; + Request nextRequest(); + + std::optional stateTransition(unsigned int from); + +private: + uint64_t requestsInState = 0; + unsigned int currentState = 0; + const std::vector stateTransistions; + + using IdleClks = uint64_t; + std::unordered_map idleStateClks; + + std::default_random_engine randomGenerator; + + std::unordered_map> producers; + RequestIssuer consumer; +}; diff --git a/src/simulator/simulator/generator/definitions.h b/src/simulator/simulator/generator/definitions.h new file mode 100644 index 00000000..98563553 --- /dev/null +++ b/src/simulator/simulator/generator/definitions.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include + +inline constexpr uint64_t DEFAULT_SEED = 0; +inline constexpr uint64_t DEFAULT_MIN_ADDRESS = 0; diff --git a/src/configuration/DRAMSys/config/memspec/MemSpec.cpp b/src/simulator/simulator/hammer/RowHammer.cpp similarity index 56% rename from src/configuration/DRAMSys/config/memspec/MemSpec.cpp rename to src/simulator/simulator/hammer/RowHammer.cpp index 2da6b91d..c1bef363 100644 --- a/src/configuration/DRAMSys/config/memspec/MemSpec.cpp +++ b/src/simulator/simulator/hammer/RowHammer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Technische Universität Kaiserslautern + * Copyright (c) 2023, Technische Universität Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,46 +33,35 @@ * Derek Christ */ -#include "MemSpec.h" +#include "RowHammer.h" -namespace DRAMSys::Config +RowHammer::RowHammer(uint64_t numRequests, + unsigned int clkMhz, + uint64_t rowIncrement, + unsigned int dataLength) + : numberOfRequests(numRequests), + generatorPeriod(sc_core::sc_time(1.0 / static_cast(clkMhz), sc_core::SC_US)), + dataLength(dataLength), + rowIncrement(rowIncrement) { - -void to_json(json &j, const MemSpec &c) -{ - j = json{{"memarchitecturespec", c.memArchitectureSpec}, - {"memoryId", c.memoryId}, - {"memoryType", c.memoryType}, - {"memtimingspec", c.memTimingSpec}, - {"mempowerspec", c.memPowerSpec}}; - - remove_null_values(j); } -void from_json(const json &j, MemSpec &c) +Request RowHammer::nextRequest() { - json j_memspecs = get_config_json(j, memSpecPath, "memspec"); + if (generatedRequests >= numberOfRequests) + return Request{.command = Request::Command::Stop}; + + generatedRequests++; - j_memspecs.at("memarchitecturespec").get_to(c.memArchitectureSpec); - j_memspecs.at("memoryId").get_to(c.memoryId); - j_memspecs.at("memoryType").get_to(c.memoryType); - j_memspecs.at("memtimingspec").get_to(c.memTimingSpec); + if (currentAddress == 0x00) + currentAddress = rowIncrement; + else + currentAddress = 0x00; - if (j_memspecs.contains("mempowerspec")) - j_memspecs.at("mempowerspec").get_to(c.memPowerSpec); + Request request; + request.address = currentAddress; + request.command = Request::Command::Read; + request.length = dataLength; + request.delay = generatorPeriod; + return request; } - -void from_dump(const std::string &dump, MemSpec &c) -{ - json json_memspec = json::parse(dump).at("memspec"); - json_memspec.get_to(c); -} - -std::string dump(const MemSpec &c, unsigned int indentation) -{ - json json_memspec; - json_memspec["memspec"] = c; - return json_memspec.dump(indentation); -} - -} // namespace Configuration diff --git a/src/simulator/simulator/hammer/RowHammer.h b/src/simulator/simulator/hammer/RowHammer.h new file mode 100644 index 00000000..78a7c579 --- /dev/null +++ b/src/simulator/simulator/hammer/RowHammer.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include "simulator/request/RequestProducer.h" + +#include + +class RowHammer : public RequestProducer +{ +public: + RowHammer(uint64_t numRequests, + unsigned int clkMhz, + uint64_t rowIncrement, + unsigned int dataLength); + + Request nextRequest() override; + sc_core::sc_time clkPeriod() override { return generatorPeriod; } + uint64_t totalRequests() override { return numberOfRequests; } + + const uint64_t numberOfRequests; + const sc_core::sc_time generatorPeriod; + const unsigned int dataLength; + const uint64_t rowIncrement; + + uint64_t generatedRequests = 0; + uint64_t currentAddress = 0x00; +}; diff --git a/src/simulator/simulator/main.cpp b/src/simulator/simulator/main.cpp deleted file mode 100644 index 3f04a683..00000000 --- a/src/simulator/simulator/main.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Robert Gernhardt - * Matthias Jung - * Luiza Correa - * Lukas Steiner - * Derek Christ - */ - -#include "simulator/TraceSetup.h" -#include "simulator/TrafficInitiator.h" - -#include "DRAMSys/simulation/DRAMSys.h" -#include "DRAMSys/simulation/DRAMSysRecordable.h" -#include "DRAMSys/config/DRAMSysConfiguration.h" - -#include -#include -#include -#include -#include -#include - -using namespace sc_core; - -std::string pathOfFile(const std::string &file) -{ - return file.substr(0, file.find_last_of('/')); -} - -int main(int argc, char **argv) -{ - return sc_main(argc, argv); -} - -int sc_main(int argc, char **argv) -{ - sc_set_time_resolution(1, SC_PS); - - std::string resources; - std::string simulationJson; - // Run only with default config (ddr3-example.json): - if (argc == 1) - { - // Get path of resources: - resources = pathOfFile(argv[0]) - + std::string("/../../configs/"); - simulationJson = resources + "ddr4-example.json"; - } - // Run with specific config but default resource folders: - else if (argc == 2) - { - // Get path of resources: - resources = pathOfFile(argv[0]) - + std::string("/../../configs/"); - simulationJson = argv[1]; - } - // Run with specific config and specific resource folder: - else if (argc == 3) - { - simulationJson = argv[1]; - resources = argv[2]; - } - - std::vector> players; - - DRAMSys::Config::Configuration configLib = DRAMSys::Config::from_path(simulationJson, resources); - - // Instantiate DRAMSys: - std::unique_ptr dramSys; - - if (configLib.simConfig.databaseRecording.value_or(false)) - dramSys = std::make_unique("DRAMSys", configLib); - else - dramSys = std::make_unique("DRAMSys", configLib); - - if (!configLib.traceSetup.has_value()) - SC_REPORT_FATAL("sc_main", "No trace setup section provided."); - - // Instantiate STL Players: - TraceSetup setup(dramSys->getConfig(), configLib.traceSetup.value(), resources, players); - - // Bind STL Players with DRAMSys: - for (auto& player : players) - player->iSocket.bind(dramSys->tSocket); - - // Store the starting of the simulation in wall-clock time: - auto start = std::chrono::high_resolution_clock::now(); - - // Start SystemC Simulation: - sc_set_stop_mode(SC_STOP_FINISH_DELTA); - sc_start(); - - if (!sc_end_of_simulation_invoked()) - { - SC_REPORT_WARNING("sc_main", "Simulation stopped without explicit sc_stop()"); - sc_stop(); - } - - auto finish = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed = finish - start; - std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl; - return 0; -} diff --git a/src/simulator/simulator/player/StlPlayer.cpp b/src/simulator/simulator/player/StlPlayer.cpp new file mode 100644 index 00000000..fb3c2017 --- /dev/null +++ b/src/simulator/simulator/player/StlPlayer.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Janik Schlemminger + * Robert Gernhardt + * Matthias Jung + * Éder F. Zulian + * Felipe S. Prado + * Derek Christ + */ + +#include "StlPlayer.h" + +#include + +StlPlayer::StlPlayer(std::string_view tracePath, + unsigned int clkMhz, + unsigned int defaultDataLength, + TraceType traceType, + bool storageEnabled) + : traceFile(tracePath.data()), + playerPeriod(sc_core::sc_time(1.0 / static_cast(clkMhz), sc_core::SC_US)), + defaultDataLength(defaultDataLength), + traceType(traceType), + storageEnabled(storageEnabled), + lineBuffers( + {std::make_shared>(), std::make_shared>()}), + readoutBuffer(lineBuffers.at(0)), + parseBuffer(lineBuffers.at(1)) +{ + readoutBuffer->reserve(LINE_BUFFER_SIZE); + parseBuffer->reserve(LINE_BUFFER_SIZE); + + if (!traceFile.is_open()) + SC_REPORT_FATAL("StlPlayer", + (std::string("Could not open trace ") + tracePath.data()).c_str()); + + { + std::string line; + while (std::getline(traceFile, line)) + { + if (line.size() > 1 && line[0] != '#') + numberOfLines++; + } + traceFile.clear(); + traceFile.seekg(0); + } + + parseTraceFile(); + readoutIt = readoutBuffer->cend(); +} + +Request StlPlayer::nextRequest() +{ + if (readoutIt == readoutBuffer->cend()) + { + readoutIt = swapBuffers(); + if (readoutIt == readoutBuffer->cend()) + { + if (parserThread.joinable()) + parserThread.join(); + + // The file is read in completely. Nothing more to do. + return Request{.command = Request::Command::Stop}; + } + } + + sc_core::sc_time delay = readoutIt->delay; + sc_core::sc_time offset = playerPeriod - (sc_core::sc_time_stamp() % playerPeriod); + + if (traceType == TraceType::Absolute) + { + delay = std::max(sc_core::sc_time_stamp() + offset, delay); + delay -= sc_core::sc_time_stamp(); + } + else // if (traceType == TraceType::Relative) + { + delay = offset + delay; + } + + Request request(*readoutIt); + request.delay = delay; + + readoutIt++; + return request; +} + +void StlPlayer::parseTraceFile() +{ + unsigned parsedLines = 0; + parseBuffer->clear(); + + while (traceFile && !traceFile.eof() && parsedLines < LINE_BUFFER_SIZE) + { + // Get a new line from the input file. + std::string line; + std::getline(traceFile, line); + currentLine++; + + // If the line is empty (\n or \r\n) or starts with '#' (comment) the transaction is + // ignored. + if (line.size() <= 1 || line.at(0) == '#') + continue; + + parsedLines++; + parseBuffer->emplace_back(); + Request &content = parseBuffer->back(); + + // Trace files MUST provide timestamp, command and address for every + // transaction. The data information depends on the storage mode + // configuration. + std::string element; + std::istringstream iss; + + iss.str(line); + + // Get the timestamp for the transaction. + iss >> element; + if (element.empty()) + SC_REPORT_FATAL( + "StlPlayer", + ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + + content.delay = playerPeriod * static_cast(std::stoull(element)); + + // Get the optional burst length and command + iss >> element; + if (element.empty()) + SC_REPORT_FATAL( + "StlPlayer", + ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + + if (element.at(0) == '(') + { + element.erase(0, 1); + content.length = std::stoul(element); + iss >> element; + if (element.empty()) + SC_REPORT_FATAL( + "StlPlayer", + ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + } + else + content.length = defaultDataLength; + + if (element == "read") + content.command = Request::Command::Read; + else if (element == "write") + content.command = Request::Command::Write; + else + SC_REPORT_FATAL( + "StlPlayer", + ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + + // Get the address. + iss >> element; + if (element.empty()) + SC_REPORT_FATAL( + "StlPlayer", + ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + content.address = std::stoull(element, nullptr, 16); + + // Get the data if necessary. + if (storageEnabled && content.command == Request::Command::Write) + { + // The input trace file must provide the data to be stored into the memory. + iss >> element; + + // Check if data length in the trace file is correct. + // We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix. + if (element.length() != (content.length * 2 + 2)) + SC_REPORT_FATAL( + "StlPlayer", + ("Malformed trace file line " + std::to_string(currentLine) + ".").c_str()); + + // Set data + for (unsigned i = 0; i < content.length; i++) + content.data.emplace_back(static_cast( + std::stoi(element.substr(i * 2 + 2, 2), nullptr, 16))); + } + } +} + +std::vector::const_iterator StlPlayer::swapBuffers() +{ + // Wait for parser to finish + if (parserThread.joinable()) + parserThread.join(); + + // Swap buffers + std::swap(readoutBuffer, parseBuffer); + + // Start new parser thread + parserThread = std::thread(&StlPlayer::parseTraceFile, this); + + return readoutBuffer->cbegin(); +} diff --git a/src/simulator/simulator/StlPlayer.h b/src/simulator/simulator/player/StlPlayer.h similarity index 57% rename from src/simulator/simulator/StlPlayer.h rename to src/simulator/simulator/player/StlPlayer.h index 35406468..e9d4b8b1 100644 --- a/src/simulator/simulator/StlPlayer.h +++ b/src/simulator/simulator/player/StlPlayer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Technische Universität Kaiserslautern + * Copyright (c) 2023, Technische Universität Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,65 +38,59 @@ * Derek Christ */ -#ifndef STLPLAYER_H -#define STLPLAYER_H +#pragma once -#include "simulator/TraceSetup.h" -#include "simulator/TrafficInitiator.h" +#include "simulator/request/Request.h" +#include "simulator/request/RequestProducer.h" -#include -#include -#include -#include -#include #include #include -class StlPlayer : public TrafficInitiator +#include +#include +#include +#include + +class StlPlayer : public RequestProducer { public: - StlPlayer(const sc_core::sc_module_name &name, - const Configuration& config, - const std::string &pathToTrace, - const sc_core::sc_time &playerClk, - unsigned int maxPendingReadRequests, - unsigned int maxPendingWriteRequests, - TraceSetup& setup, - bool relative); - - ~StlPlayer() override; - void sendNextPayload() override; - uint64_t getNumberOfLines() const; - -private: - struct LineContent + enum class TraceType { - sc_core::sc_time sendingTime; - unsigned dataLength; - tlm::tlm_command command; - uint64_t address; - std::vector data; + Absolute, + Relative, }; - void parseTraceFile(); - std::vector::const_iterator swapBuffers(); + StlPlayer(std::string_view tracePath, + unsigned int clkMhz, + unsigned int defaultDataLength, + TraceType traceType, + bool storageEnabled); - std::ifstream file; - uint64_t lineCnt = 0; + Request nextRequest() override; + + sc_core::sc_time clkPeriod() override { return playerPeriod; } + uint64_t totalRequests() override { return numberOfLines; } + +private: + void parseTraceFile(); + std::vector::const_iterator swapBuffers(); + + static constexpr std::size_t LINE_BUFFER_SIZE = 10000; + + const TraceType traceType; + const bool storageEnabled; + const sc_core::sc_time playerPeriod; + const unsigned int defaultDataLength; + + std::ifstream traceFile; + uint64_t currentLine = 0; uint64_t numberOfLines = 0; - const sc_core::sc_time playerClk; // May be different from the memory clock! + std::array>, 2> lineBuffers; + std::shared_ptr> parseBuffer; + std::shared_ptr> readoutBuffer; - static constexpr unsigned lineBufferSize = 10000; - - std::vector* currentBuffer; - std::vector* parseBuffer; - std::array, 2> lineContents; - std::vector::const_iterator lineIterator; + std::vector::const_iterator readoutIt; std::thread parserThread; - - const bool relative; }; - -#endif // STLPLAYER_H diff --git a/src/configuration/DRAMSys/config/ConfigUtil.cpp b/src/simulator/simulator/request/Request.h similarity index 66% rename from src/configuration/DRAMSys/config/ConfigUtil.cpp rename to src/simulator/simulator/request/Request.h index 8024cfee..7ee69d82 100644 --- a/src/configuration/DRAMSys/config/ConfigUtil.cpp +++ b/src/simulator/simulator/request/Request.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Technische Universität Kaiserslautern + * Copyright (c) 2023, Technische Universität Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,31 +33,21 @@ * Derek Christ */ -#include "ConfigUtil.h" +#pragma once -#include "DRAMSys/config/DRAMSysConfiguration.h" +#include +#include -#include -#include - -namespace DRAMSys::Config +struct Request { - - json_t get_config_json(const json_t& j, const std::string& configPath, const std::string& objectName) + enum class Command { - if (j.is_object()) - { - return j; - } - else // j should be a string path to the real json file - { - std::string jsonFileName; - j.get_to(jsonFileName); - - std::ifstream file(std::string(Configuration::resourceDirectory) + "/" + configPath + "/" + jsonFileName); - json_t j_object = json_t::parse(file); - return j_object.at(objectName); - } - } - -} // namespace DRAMSys::Config + Read, + Write, + Stop + } command; + uint64_t address; + std::size_t length; + sc_core::sc_time delay; + std::vector data; +}; diff --git a/src/simulator/simulator/request/RequestIssuer.cpp b/src/simulator/simulator/request/RequestIssuer.cpp new file mode 100644 index 00000000..5913e54e --- /dev/null +++ b/src/simulator/simulator/request/RequestIssuer.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "RequestIssuer.h" + +RequestIssuer::RequestIssuer(sc_core::sc_module_name const &name, + MemoryManager &memoryManager, + std::optional maxPendingReadRequests, + std::optional maxPendingWriteRequests, + std::function nextRequest, + std::function transactionFinished, + std::function terminate) + : sc_module(name), + memoryManager(memoryManager), + maxPendingReadRequests(maxPendingReadRequests), + maxPendingWriteRequests(maxPendingWriteRequests), + nextRequest(std::move(nextRequest)), + transactionFinished(std::move(transactionFinished)), + terminate(std::move(terminate)), + payloadEventQueue(this, &RequestIssuer::peqCallback) +{ + SC_THREAD(sendNextRequest); + iSocket.register_nb_transport_bw(this, &RequestIssuer::nb_transport_bw); +} + +void RequestIssuer::sendNextRequest() +{ + Request request = nextRequest(); + + if (request.command == Request::Command::Stop) + { + finished = true; + return; + } + + tlm::tlm_generic_payload &payload = memoryManager.allocate(request.length); + payload.acquire(); + payload.set_address(request.address); + payload.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + payload.set_dmi_allowed(false); + payload.set_byte_enable_length(0); + payload.set_data_length(request.length); + payload.set_streaming_width(request.length); + payload.set_command(request.command == Request::Command::Read ? tlm::TLM_READ_COMMAND + : tlm::TLM_WRITE_COMMAND); + + tlm::tlm_phase phase = tlm::BEGIN_REQ; + sc_core::sc_time delay = request.delay; + + if (request.address == 0x4000f000) + int x = 0; + + if (transactionsSent == 0) + delay = sc_core::SC_ZERO_TIME; + + iSocket->nb_transport_fw(payload, phase, delay); + transactionInProgress = true; + + if (request.command == Request::Command::Read) + pendingReadRequests++; + else if (request.command == Request::Command::Write) + pendingWriteRequests++; + + transactionsSent++; +} + +bool RequestIssuer::nextRequestSendable() const +{ + // If either the maxPendingReadRequests or maxPendingWriteRequests + // limit is reached, do not send next payload. + if (maxPendingReadRequests.has_value() && pendingReadRequests >= maxPendingReadRequests.value()) + return false; + + if (maxPendingWriteRequests.has_value() && + pendingWriteRequests >= maxPendingWriteRequests.value()) + return false; + + return true; +} + +void RequestIssuer::peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase) +{ + if (phase == tlm::END_REQ) + { + if (nextRequestSendable()) + sendNextRequest(); + else + transactionPostponed = true; + } + else if (phase == tlm::BEGIN_RESP) + { + tlm::tlm_phase phase = tlm::END_RESP; + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + iSocket->nb_transport_fw(payload, phase, delay); + + payload.release(); + transactionInProgress = false; + + transactionFinished(); + + transactionsReceived++; + + if (payload.get_command() == tlm::TLM_READ_COMMAND) + pendingReadRequests--; + else if (payload.get_command() == tlm::TLM_WRITE_COMMAND) + pendingWriteRequests--; + + // If the initiator wasn't able to send the next payload in the END_REQ phase, do it + // now. + if (transactionPostponed && nextRequestSendable()) + { + sendNextRequest(); + transactionPostponed = false; + } + + // If all answers were received: + if (finished && transactionsSent == transactionsReceived) + terminate(); + } + else + { + SC_REPORT_FATAL("TrafficInitiator", "PEQ was triggered with unknown phase"); + } +} diff --git a/src/simulator/simulator/TrafficInitiator.h b/src/simulator/simulator/request/RequestIssuer.h similarity index 55% rename from src/simulator/simulator/TrafficInitiator.h rename to src/simulator/simulator/request/RequestIssuer.h index ad3b00ca..7f712997 100644 --- a/src/simulator/simulator/TrafficInitiator.h +++ b/src/simulator/simulator/request/RequestIssuer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Technische Universität Kaiserslautern + * Copyright (c) 2023, Technische Universität Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,70 +30,67 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: - * Robert Gernhardt - * Matthias Jung - * Éder F. Zulian - * Felipe S. Prado * Derek Christ */ -#ifndef TRAFFICINITIATOR_H -#define TRAFFICINITIATOR_H +#pragma once -#include "simulator/TraceSetup.h" +#include "Request.h" +#include "simulator/MemoryManager.h" -#include "DRAMSys/configuration/Configuration.h" -#include "DRAMSys/common/DebugManager.h" - -#include -#include -#include -#include #include -#include +#include #include +#include -class TrafficInitiator : public sc_core::sc_module +#include + +class RequestIssuer : sc_core::sc_module { public: - tlm_utils::simple_initiator_socket iSocket; - TrafficInitiator(const sc_core::sc_module_name &name, const Configuration& config, TraceSetup& setup, - unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests, unsigned int defaultDataLength); - SC_HAS_PROCESS(TrafficInitiator); - virtual void sendNextPayload() = 0; + tlm_utils::simple_initiator_socket iSocket; -protected: - static sc_core::sc_time evaluateGeneratorClk(const DRAMSys::Config::TrafficInitiator &conf); - - tlm_utils::peq_with_cb_and_phase payloadEventQueue; - void terminate(); - TraceSetup& setup; - void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase, - const sc_core::sc_time &delay); - - uint64_t transactionsReceived = 0; - uint64_t transactionsSent = 0; - unsigned int pendingReadRequests = 0; - unsigned int pendingWriteRequests = 0; - - const unsigned int maxPendingReadRequests = 0; - const unsigned int maxPendingWriteRequests = 0; - - bool payloadPostponed = false; - bool finished = false; - const unsigned int defaultDataLength; - const bool storageEnabled; - const bool simulationProgressBar; - - // 0 disables the max value. - static constexpr unsigned int defaultMaxPendingWriteRequests = 0; - static constexpr unsigned int defaultMaxPendingReadRequests = 0; + RequestIssuer(sc_core::sc_module_name const &name, + MemoryManager &memoryManager, + std::optional maxPendingReadRequests, + std::optional maxPendingWriteRequests, + std::function nextRequest, + std::function transactionFinished, + std::function terminate); + SC_HAS_PROCESS(RequestIssuer); private: - tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, - sc_core::sc_time &bwDelay); - void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); - bool nextPayloadSendable() const; -}; + tlm_utils::peq_with_cb_and_phase payloadEventQueue; + MemoryManager &memoryManager; -#endif // TRAFFICINITIATOR_H + bool transactionInProgress = false; + bool transactionPostponed = false; + bool finished = false; + + uint64_t transactionsSent = 0; + uint64_t transactionsReceived = 0; + + unsigned int pendingReadRequests = 0; + unsigned int pendingWriteRequests = 0; + const std::optional maxPendingReadRequests; + const std::optional maxPendingWriteRequests; + + unsigned int activeProducers = 0; + + std::function transactionFinished; + std::function terminate; + std::function nextRequest; + + void sendNextRequest(); + bool nextRequestSendable() const; + + tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, + tlm::tlm_phase &phase, + sc_core::sc_time &bwDelay) + { + payloadEventQueue.notify(payload, phase, bwDelay); + return tlm::TLM_ACCEPTED; + } + + void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); +}; diff --git a/src/simulator/simulator/request/RequestProducer.h b/src/simulator/simulator/request/RequestProducer.h new file mode 100644 index 00000000..4a6eee73 --- /dev/null +++ b/src/simulator/simulator/request/RequestProducer.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include "Request.h" + +class RequestProducer +{ +public: + virtual ~RequestProducer() = default; + + virtual Request nextRequest() = 0; + virtual uint64_t totalRequests() = 0; + virtual sc_core::sc_time clkPeriod() = 0; + virtual void reset(){}; +}; diff --git a/src/simulator/simulator/util.cpp b/src/simulator/simulator/util.cpp new file mode 100644 index 00000000..4c04bb32 --- /dev/null +++ b/src/simulator/simulator/util.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Matthias Jung + * Derek Christ + */ + +#include "util.h" + +#include +#include +#include + +void loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity) +{ + if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0))) + return; + + float ratio = x / (float)n; + unsigned int c = (ratio * w); + float rest = (ratio * w) - c; + std::cout << std::setw(3) << std::round(ratio * 100) << "% |"; + for (unsigned int x = 0; x < c; x++) + std::cout << "█"; + + if (rest >= 0 && rest < 0.125f && c != w) + std::cout << " "; + if (rest >= 0.125f && rest < 2 * 0.125f) + std::cout << "▏"; + if (rest >= 2 * 0.125f && rest < 3 * 0.125f) + std::cout << "▎"; + if (rest >= 3 * 0.125f && rest < 4 * 0.125f) + std::cout << "▍"; + if (rest >= 4 * 0.125f && rest < 5 * 0.125f) + std::cout << "▌"; + if (rest >= 5 * 0.125f && rest < 6 * 0.125f) + std::cout << "▋"; + if (rest >= 6 * 0.125f && rest < 7 * 0.125f) + std::cout << "▊"; + if (rest >= 7 * 0.125f && rest < 8 * 0.125f) + std::cout << "▉"; + + for (unsigned int x = c; x < (w - 1); x++) + std::cout << " "; + std::cout << "|\r" << std::flush; +} diff --git a/src/simulator/simulator/TraceSetup.h b/src/simulator/simulator/util.h similarity index 58% rename from src/simulator/simulator/TraceSetup.h rename to src/simulator/simulator/util.h index 57913573..160d2367 100644 --- a/src/simulator/simulator/TraceSetup.h +++ b/src/simulator/simulator/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Technische Universität Kaiserslautern + * Copyright (c) 2023, Technische Universität Kaiserslautern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,43 +34,8 @@ * Derek Christ */ -#ifndef TRACESETUP_H -#define TRACESETUP_H +#pragma once -#include "simulator/MemoryManager.h" +#include -#include "DRAMSys/config/DRAMSysConfiguration.h" -#include "DRAMSys/configuration/Configuration.h" - -#include -#include -#include -#include - -class TrafficInitiator; - -class TraceSetup -{ -public: - TraceSetup(const Configuration& config, - const DRAMSys::Config::TraceSetup &traceSetup, - const std::string &pathToResources, - std::vector> &devices); - - void trafficInitiatorTerminates(); - void transactionFinished(); - tlm::tlm_generic_payload& allocatePayload(unsigned dataLength); - tlm::tlm_generic_payload& allocatePayload(); - -private: - unsigned int numberOfTrafficInitiators; - uint64_t totalTransactions = 0; - uint64_t remainingTransactions; - unsigned int finishedTrafficInitiators = 0; - MemoryManager memoryManager; - unsigned defaultDataLength = 64; - - static void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1); -}; - -#endif // TRACESETUP_H +void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1); diff --git a/src/util/DRAMSys/util/json.h b/src/util/DRAMSys/util/json.h index f184f8a1..ae8c047c 100644 --- a/src/util/DRAMSys/util/json.h +++ b/src/util/DRAMSys/util/json.h @@ -31,6 +31,7 @@ * * Authors: * Thomas Psota + * Derek Christ */ @@ -40,11 +41,83 @@ #include "nlohmann/json.hpp" #include +#include +#include using json_t = nlohmann::json; +namespace DRAMSys::util { +// See https://www.kdab.com/jsonify-with-nlohmann-json/ +// Try to set the value of type T into the variant data if it fails, do nothing +template +void variant_from_json(const nlohmann::json &j, std::variant &data) +{ + try { + data = j.get(); + } catch (...) { + } +} + +template +void optional_to_json(nlohmann::json &j, std::string_view name, const std::optional &value) +{ + if (value) + j[name] = *value; +} + +template +void optional_from_json(const nlohmann::json &j, std::string_view name, std::optional &value) +{ + const auto it = j.find(name); + + if (it != j.end()) + value = it->get(); + else + value = std::nullopt; +} + +template +constexpr bool is_optional = false; +template +constexpr bool is_optional> = true; + +template +void extended_to_json(const char *key, nlohmann::json &j, const T &value) +{ + if constexpr (is_optional) + optional_to_json(j, key, value); + else + j[key] = value; +} + +template +void extended_from_json(const char *key, const nlohmann::json &j, T &value) +{ + if constexpr (is_optional) + optional_from_json(j, key, value); + else + j.at(key).get_to(value); +} + +} // namespace DRAMSys::util + NLOHMANN_JSON_NAMESPACE_BEGIN +template +struct adl_serializer> +{ + static void to_json(nlohmann::json &j, const std::variant &data) + { + std::visit([&j](const auto &v) { j = v; }, data); + } + + static void from_json(const nlohmann::json &j, std::variant &data) + { + // Call variant_from_json for all types, only one will succeed + (DRAMSys::util::variant_from_json(j, data), ...); + } +}; + template struct adl_serializer> { static void to_json(json_t& j, const std::optional& opt) { @@ -66,6 +139,18 @@ struct adl_serializer> { } }; + NLOHMANN_JSON_NAMESPACE_END +#define EXTEND_JSON_TO(v1) DRAMSys::util::extended_to_json(#v1, nlohmann_json_j, nlohmann_json_t.v1); +#define EXTEND_JSON_FROM(v1) DRAMSys::util::extended_from_json(#v1, nlohmann_json_j, nlohmann_json_t.v1); + +#define NLOHMANN_JSONIFY_ALL_THINGS(Type, ...) \ + inline void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \ + NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_TO, __VA_ARGS__)) \ + } \ + inline void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \ + NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, __VA_ARGS__)) \ + } + #endif \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4702149b..a89ad8d0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,3 +4,4 @@ add_subdirectory(tests_configuration) add_subdirectory(tests_dramsys) add_subdirectory(tests_regression) add_subdirectory(tests_util) +add_subdirectory(tests_simulator) diff --git a/tests/tests_configuration/CMakeLists.txt b/tests/tests_configuration/CMakeLists.txt index e1eee0f6..baab76cc 100644 --- a/tests/tests_configuration/CMakeLists.txt +++ b/tests/tests_configuration/CMakeLists.txt @@ -1,8 +1,26 @@ -add_executable(simpletest "${CMAKE_CURRENT_LIST_DIR}/simpletest.cpp") -target_link_libraries(simpletest PRIVATE DRAMSys::config) -set_target_properties(simpletest PROPERTIES FOLDER tests/configuration) +############################################### +### tests_configuration ### +############################################### +cmake_minimum_required(VERSION 3.1.0) -add_executable(converter "${CMAKE_CURRENT_LIST_DIR}/converter.cpp") -target_link_libraries(converter PRIVATE DRAMSys::config) -set_target_properties(converter PROPERTIES FOLDER tests/configuration) +project(tests_configuration) + +add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/test_configuration.cpp) + +set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER tests/configuration) + +target_link_libraries(${PROJECT_NAME} PRIVATE + DRAMSys::config + gtest_main +) + +gtest_discover_tests(${PROJECT_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_executable(jsonconverter ${CMAKE_CURRENT_SOURCE_DIR}/jsonconverter.cpp) +target_link_libraries(jsonconverter PRIVATE DRAMSys::config) +set_target_properties(jsonconverter PROPERTIES FOLDER tests/configuration) + +build_source_group() diff --git a/tests/tests_configuration/converter.cpp b/tests/tests_configuration/jsonconverter.cpp similarity index 100% rename from tests/tests_configuration/converter.cpp rename to tests/tests_configuration/jsonconverter.cpp index c7f4845d..92f341e3 100644 --- a/tests/tests_configuration/converter.cpp +++ b/tests/tests_configuration/jsonconverter.cpp @@ -33,12 +33,12 @@ * Derek Christ */ +#include + #include #include #include -#include - int main(int argc, char **argv) { if (argc != 2) diff --git a/tests/tests_configuration/reference.json b/tests/tests_configuration/reference.json new file mode 100644 index 00000000..42d01beb --- /dev/null +++ b/tests/tests_configuration/reference.json @@ -0,0 +1,210 @@ +{ + "simulation": { + "addressmapping": { + "BANKGROUP_BIT": [ + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "BANK_BIT": [ + 13, + 14, + 15 + ], + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "RANK_BIT": [ + 33 + ], + "ROW_BIT": [ + 16 + ] + }, + "mcconfig": { + "Arbiter": "Simple", + "CmdMux": "Oldest", + "HighWatermark": 0, + "LowWatermark": 0, + "MaxActiveTransactions": 128, + "PagePolicy": "Open", + "PowerDownPolicy": "NoPowerDown", + "RefreshMaxPostponed": 0, + "RefreshMaxPulledin": 0, + "RefreshPolicy": "AllBank", + "RequestBufferSize": 8, + "RespQueue": "Fifo", + "Scheduler": "FrFcfs", + "SchedulerBuffer": "Bankwise" + }, + "memspec": { + "memarchitecturespec": { + "RAACDR": 1, + "RAAIMT": 32, + "RAAMMT": 96, + "burstLength": 16, + "cmdMode": 1, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfChannels": 2, + "nbrOfColumns": 2048, + "nbrOfDIMMRanks": 1, + "nbrOfDevices": 8, + "nbrOfLogicalRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfRanks": 1, + "nbrOfRows": 65536, + "refMode": 1, + "width": 4 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-3200A", + "memoryType": "DDR5", + "memtimingspec": { + "ACTPDEN": 2, + "CCD_L_WR2_slr": 16, + "CCD_L_WR_slr": 32, + "CCD_L_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_S_slr": 8, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "CCD_dlr": 0, + "CPDED": 8, + "FAW_dlr": 0, + "FAW_slr": 32, + "PD": 12, + "PPD": 2, + "PRPDEN": 2, + "RAS": 52, + "RCD": 22, + "RDDQS": 0, + "REFI1": 6240, + "REFI2": 3120, + "REFISB": 1560, + "REFPDEN": 2, + "REFSBRD_dlr": 0, + "REFSBRD_slr": 48, + "RFC1_dlr": 0, + "RFC1_dpr": 0, + "RFC1_slr": 312, + "RFC2_dlr": 0, + "RFC2_dpr": 0, + "RFC2_slr": 208, + "RFCsb_dlr": 0, + "RFCsb_slr": 184, + "RL": 22, + "RP": 22, + "RPRE": 1, + "RPST": 0, + "RRD_L_slr": 8, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "RTP": 12, + "RTRS": 2, + "WL": 20, + "WPRE": 2, + "WPST": 0, + "WR": 48, + "WTR_L": 16, + "WTR_S": 4, + "XP": 12, + "clkMhz": 1600 + } + }, + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "EnableWindowing": false, + "ErrorCSVFile": "error.csv", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "ddr5", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + }, + "simulationid": "std::string_simulationId", + "tracesetup": [ + { + "clkMhz": 100, + "name": "mytrace.stl" + }, + { + "addressDistribution": "random", + "clkMhz": 100, + "name": "MyTestGen", + "numRequests": 1000, + "rwRatio": 0.5 + }, + { + "clkMhz": 100, + "maxPendingReadRequests": 8, + "name": "MyTestGen", + "states": [ + { + "addressDistribution": "sequential", + "addressIncrement": 256, + "id": 0, + "maxAddress": 1024, + "numRequests": 1000, + "rwRatio": 0.5 + }, + { + "addressDistribution": "sequential", + "addressIncrement": 512, + "id": 1, + "maxAddress": 2048, + "minAddress": 1024, + "numRequests": 100, + "rwRatio": 0.75 + } + ], + "transitions": [ + { + "from": 0, + "probability": 1.0, + "to": 1 + } + ] + }, + { + "clkMhz": 100, + "name": "MyTestHammer", + "numRequests": 4000, + "rowIncrement": 2097152 + } + ] + } +} \ No newline at end of file diff --git a/tests/tests_configuration/resources/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json b/tests/tests_configuration/resources/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json new file mode 100644 index 00000000..143f714a --- /dev/null +++ b/tests/tests_configuration/resources/addressmapping/am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json @@ -0,0 +1,50 @@ +{ + "addressmapping": { + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "BANKGROUP_BIT": [ + 13, + 14, + 15 + ], + "BANK_BIT": [ + 16 + ], + "ROW_BIT": [ + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "CHANNEL_BIT": [ + 33 + ] + } +} \ No newline at end of file diff --git a/tests/tests_configuration/resources/ddr5-example.json b/tests/tests_configuration/resources/ddr5-example.json new file mode 100644 index 00000000..2fea61ee --- /dev/null +++ b/tests/tests_configuration/resources/ddr5-example.json @@ -0,0 +1,11 @@ +{ + "simulation": { + "addressmapping": "am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json", + "mcconfig": "fr_fcfs.json", + "memspec": "JEDEC_2x8x2Gbx4_DDR5-3200A.json", + "simconfig": "ddr5.json", + "simulationid": "ddr5-example", + "thermalconfig": "config.json", + "tracesetup": "ddr5-trace.json" + } +} diff --git a/tests/tests_configuration/resources/mcconfig/fr_fcfs.json b/tests/tests_configuration/resources/mcconfig/fr_fcfs.json new file mode 100644 index 00000000..cdaa94b3 --- /dev/null +++ b/tests/tests_configuration/resources/mcconfig/fr_fcfs.json @@ -0,0 +1,17 @@ +{ + "mcconfig": { + "PagePolicy": "Open", + "Scheduler": "FrFcfs", + "SchedulerBuffer": "Bankwise", + "RequestBufferSize": 8, + "CmdMux": "Oldest", + "RespQueue": "Fifo", + "RefreshPolicy": "AllBank", + "RefreshMaxPostponed": 0, + "RefreshMaxPulledin": 0, + "PowerDownPolicy": "NoPowerDown", + "Arbiter": "Simple", + "MaxActiveTransactions": 128, + "RefreshManagement": false + } +} diff --git a/tests/tests_configuration/resources/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json b/tests/tests_configuration/resources/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json new file mode 100644 index 00000000..9b3e1e4e --- /dev/null +++ b/tests/tests_configuration/resources/memspec/JEDEC_2x8x2Gbx4_DDR5-3200A.json @@ -0,0 +1,77 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 2048, + "nbrOfRanks": 1, + "nbrOfDIMMRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfLogicalRanks": 1, + "nbrOfRows": 65536, + "width": 4, + "nbrOfDevices": 8, + "nbrOfChannels": 2, + "cmdMode": 1, + "refMode": 1, + "RAAIMT" : 32, + "RAAMMT" : 96, + "RAACDR" : 16 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-3200A", + "memoryType": "DDR5", + "memtimingspec": { + "RCD": 22, + "PPD": 2, + "RP": 22, + "RAS": 52, + "RL": 22, + "RTP": 12, + "RPRE": 1, + "RPST": 0, + "RDDQS": 0, + "WL": 20, + "WPRE": 2, + "WPST": 0, + "WR": 48, + "CCD_L_slr": 8, + "CCD_L_WR_slr": 32, + "CCD_L_WR2_slr": 16, + "CCD_S_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_dlr": 0, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "RRD_L_slr": 8, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "FAW_slr": 32, + "FAW_dlr": 0, + "WTR_L": 16, + "WTR_S": 4, + "RFC1_slr": 312, + "RFC2_slr": 208, + "RFC1_dlr": 0, + "RFC2_dlr": 0, + "RFC1_dpr": 0, + "RFC2_dpr": 0, + "RFCsb_slr": 184, + "RFCsb_dlr": 0, + "REFI1": 6240, + "REFI2": 3120, + "REFISB": 1560, + "REFSBRD_slr": 48, + "REFSBRD_dlr": 0, + "RTRS": 2, + "CPDED": 8, + "PD": 12, + "XP": 12, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "clkMhz": 1600 + } + } +} diff --git a/tests/tests_configuration/resources/simconfig/ddr5.json b/tests/tests_configuration/resources/simconfig/ddr5.json new file mode 100644 index 00000000..d3987d37 --- /dev/null +++ b/tests/tests_configuration/resources/simconfig/ddr5.json @@ -0,0 +1,19 @@ +{ + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "ECCControllerMode": "Disabled", + "EnableWindowing": false, + "ErrorCSVFile": "", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "ddr5", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + } +} diff --git a/tests/tests_configuration/resources/tracesetup/ddr5-trace.json b/tests/tests_configuration/resources/tracesetup/ddr5-trace.json new file mode 100644 index 00000000..1ca86cfd --- /dev/null +++ b/tests/tests_configuration/resources/tracesetup/ddr5-trace.json @@ -0,0 +1,28 @@ +{ + "tracesetup": [ + { + "clkMhz": 2000, + "name": "ddr3_example.stl" + }, + { + "clkMhz": 2000, + "name": "gen0", + "numRequests": 2000, + "rwRatio": 0.85, + "addressDistribution": "sequential", + "addressIncrement": 256, + "maxPendingReadRequests": 8, + "maxPendingWriteRequests": 8 + }, + { + "clkMhz": 2000, + "name": "gen1", + "numRequests": 2000, + "rwRatio": 0.85, + "addressDistribution": "random", + "seed": 123456, + "maxPendingReadRequests": 8, + "maxPendingWriteRequests": 8 + } + ] +} \ No newline at end of file diff --git a/tests/tests_configuration/test_configuration.cpp b/tests/tests_configuration/test_configuration.cpp new file mode 100644 index 00000000..ca0430cf --- /dev/null +++ b/tests/tests_configuration/test_configuration.cpp @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2021, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include +#include + +#include +#include +#include +#include + +using namespace DRAMSys::Config; + +class ConfigurationTest : public ::testing::Test +{ +protected: + ConfigurationTest() + : memSpec(createMemSpec()), + tracePlayer(createTracePlayer()), + traceGeneratorOneState(createTraceGeneratorOneState()), + traceGeneratorMultipleStates(createTraceGeneratorMultipleStates()), + traceHammer(createTraceHammer()) + { + } + + static DRAMSys::Config::MemSpec createMemSpec(); + + static DRAMSys::Config::TracePlayer createTracePlayer(); + static DRAMSys::Config::TrafficGenerator createTraceGeneratorOneState(); + static DRAMSys::Config::TrafficGeneratorStateMachine createTraceGeneratorMultipleStates(); + static DRAMSys::Config::RowHammer createTraceHammer(); + + DRAMSys::Config::AddressMapping addressMapping{ + {{0, 1}}, + {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, + {{16}}, + {{13, 14, 15}}, + {{17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}}, + {{33}}, + std::nullopt, + std::nullopt, + std::nullopt}; + + DRAMSys::Config::McConfig mcConfig{PagePolicyType::Open, + SchedulerType::FrFcfs, + 0, + 0, + SchedulerBufferType::Bankwise, + 8, + CmdMuxType::Oldest, + RespQueueType::Fifo, + RefreshPolicyType::AllBank, + 0, + 0, + PowerDownPolicyType::NoPowerDown, + ArbiterType::Simple, + 128, + {}}; + + DRAMSys::Config::SimConfig simConfig{0, + false, + true, + false, + false, + {"error.csv"}, + 42, + false, + {"ddr5"}, + true, + DRAMSys::Config::StoreModeType::NoStorage, + false, + false, + 1000}; + + DRAMSys::Config::MemSpec memSpec; + + DRAMSys::Config::TracePlayer tracePlayer; + DRAMSys::Config::TrafficGenerator traceGeneratorOneState; + DRAMSys::Config::TrafficGeneratorStateMachine traceGeneratorMultipleStates; + DRAMSys::Config::RowHammer traceHammer; + DRAMSys::Config::TraceSetup traceSetup{{tracePlayer, traceGeneratorOneState, traceGeneratorMultipleStates, traceHammer}}; + + DRAMSys::Config::Configuration configuration{ + addressMapping, + mcConfig, + memSpec, + simConfig, + "std::string_simulationId", + traceSetup + }; +}; + +DRAMSys::Config::MemSpec ConfigurationTest::createMemSpec() +{ + MemArchitectureSpecType memArchitectureSpec{{{"burstLength", 16}, + {"dataRate", 2}, + {"nbrOfBankGroups", 8}, + {"nbrOfBanks", 16}, + {"nbrOfColumns", 2048}, + {"nbrOfRanks", 1}, + {"nbrOfDIMMRanks", 1}, + {"nbrOfPhysicalRanks", 1}, + {"nbrOfLogicalRanks", 1}, + {"nbrOfRows", 65536}, + {"width", 4}, + {"nbrOfDevices", 8}, + {"nbrOfChannels", 2}, + {"cmdMode", 1}, + {"refMode", 1}, + {"RAAIMT", 32}, + {"RAAMMT", 96}, + {"RAACDR", 1}}}; + + MemTimingSpecType memTimingSpec{{{ + {"RCD", 22}, {"PPD", 2}, {"RP", 22}, {"RAS", 52}, + {"RL", 22}, {"RTP", 12}, {"RPRE", 1}, {"RPST", 0}, + {"RDDQS", 0}, {"WL", 20}, {"WPRE", 2}, {"WPST", 0}, + {"WR", 48}, {"CCD_L_slr", 8}, {"CCD_L_WR_slr", 32}, {"CCD_L_WR2_slr", 16}, + {"CCD_S_slr", 8}, {"CCD_S_WR_slr", 8}, {"CCD_dlr", 0}, {"CCD_WR_dlr", 0}, + {"CCD_WR_dpr", 0}, {"RRD_L_slr", 8}, {"RRD_S_slr", 8}, {"RRD_dlr", 0}, + {"FAW_slr", 32}, {"FAW_dlr", 0}, {"WTR_L", 16}, {"WTR_S", 4}, + {"RFC1_slr", 312}, {"RFC2_slr", 208}, {"RFC1_dlr", 0}, {"RFC2_dlr", 0}, + {"RFC1_dpr", 0}, {"RFC2_dpr", 0}, {"RFCsb_slr", 184}, {"RFCsb_dlr", 0}, + {"REFI1", 6240}, {"REFI2", 3120}, {"REFISB", 1560}, {"REFSBRD_slr", 48}, + {"REFSBRD_dlr", 0}, {"RTRS", 2}, {"CPDED", 8}, {"PD", 12}, + {"XP", 12}, {"ACTPDEN", 2}, {"PRPDEN", 2}, {"REFPDEN", 2}, + {"clkMhz", 1600}, + }}}; + + return {memArchitectureSpec, "JEDEC_2x8x2Gbx4_DDR5-3200A", "DDR5", memTimingSpec, {}}; +} + +DRAMSys::Config::TracePlayer ConfigurationTest::createTracePlayer() +{ + DRAMSys::Config::TracePlayer player; + player.clkMhz = 100; + player.name = "mytrace.stl"; + + return player; +} + +DRAMSys::Config::TrafficGenerator ConfigurationTest::createTraceGeneratorOneState() +{ + DRAMSys::Config::TrafficGenerator gen; + gen.clkMhz = 100; + gen.name = "MyTestGen"; + + gen.numRequests = 1000; + gen.rwRatio = 0.5; + gen.addressDistribution = DRAMSys::Config::AddressDistribution::Random; + gen.addressIncrement = {}; + gen.minAddress = {}; + gen.maxAddress = {}; + + return gen; +} + +DRAMSys::Config::TrafficGeneratorStateMachine ConfigurationTest::createTraceGeneratorMultipleStates() +{ + DRAMSys::Config::TrafficGeneratorStateMachine gen; + + gen.clkMhz = 100; + gen.name = "MyTestGen"; + gen.maxPendingReadRequests = 8; + + DRAMSys::Config::TrafficGeneratorActiveState state0; + state0.numRequests = 1000; + state0.rwRatio = 0.5; + state0.addressDistribution = DRAMSys::Config::AddressDistribution::Sequential; + state0.addressIncrement = 256; + state0.minAddress = {}; + state0.maxAddress = 1024; + state0.id = 0; + + DRAMSys::Config::TrafficGeneratorActiveState state1; + state1.numRequests = 100; + state1.rwRatio = 0.75; + state1.addressDistribution = DRAMSys::Config::AddressDistribution::Sequential; + state1.addressIncrement = 512; + state1.minAddress = 1024; + state1.maxAddress = 2048; + state1.id = 1; + + gen.states.push_back(state0); + gen.states.push_back(state1); + + DRAMSys::Config::TrafficGeneratorStateTransition transistion0{0, 1, 1.0}; + + gen.transitions.push_back(transistion0); + + return gen; +} + +DRAMSys::Config::RowHammer ConfigurationTest::createTraceHammer() +{ + DRAMSys::Config::RowHammer hammer; + + hammer.clkMhz = 100; + hammer.name = "MyTestHammer"; + hammer.numRequests = 4000; + hammer.rowIncrement = 2097152; + + return hammer; +} + +TEST_F(ConfigurationTest, ToJson) +{ + json_t config_json; + config_json["simulation"] = configuration; + + std::ifstream file("reference.json"); + ASSERT_TRUE(file.is_open()); + + json_t reference_json = json_t::parse(file); + std::cout << reference_json.dump(4) << std::endl; + EXPECT_EQ(config_json, reference_json); +} + +TEST(Configuration, FromToJson) +{ + std::ifstream file("reference.json"); + ASSERT_TRUE(file.is_open()); + + json_t reference_json = json_t::parse(file); + DRAMSys::Config::Configuration reference_configuration = + reference_json["simulation"].get(); + + json_t new_json; + new_json["simulation"] = reference_configuration; + + EXPECT_EQ(new_json, reference_json); +} + +TEST_F(ConfigurationTest, DumpConfiguration) +{ + // This test does not test anything. It just dumps the configuration to stdout for manual + // inspection. + + json_t json; + json["simulation"] = configuration; + + std::cout << json.dump(4) << std::endl; +} + +TEST(Configuration, ResourceDirectory) +{ + // Test should not throw exceptions + Configuration config = from_path("resources/ddr5-example.json", "resources"); +} + +TEST(Configuration, FromPath) +{ + // Test should not throw exceptions + Configuration config = from_path("reference.json"); +} + +TEST_F(ConfigurationTest, SimConfig) +{ + std::string_view simconfig_string = R"( + { + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "EnableWindowing": false, + "ErrorCSVFile": "error.csv", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "ddr5", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + } + } + )"; + + json_t simconfig_reference = json_t::parse(simconfig_string); + json_t simconfig_test; + simconfig_test[SimConfig::KEY] = simConfig; + + EXPECT_EQ(simconfig_test, simconfig_reference); +} + +TEST_F(ConfigurationTest, McConfig) +{ + std::string_view mcconfig_string = R"( + { + "mcconfig": { + "Arbiter": "Simple", + "CmdMux": "Oldest", + "HighWatermark": 0, + "LowWatermark": 0, + "MaxActiveTransactions": 128, + "PagePolicy": "Open", + "PowerDownPolicy": "NoPowerDown", + "RefreshMaxPostponed": 0, + "RefreshMaxPulledin": 0, + "RefreshPolicy": "AllBank", + "RequestBufferSize": 8, + "RespQueue": "Fifo", + "Scheduler": "FrFcfs", + "SchedulerBuffer": "Bankwise" + } + } + )"; + + json_t mcconfig_reference = json_t::parse(mcconfig_string); + json_t mcconfig_test; + mcconfig_test[McConfig::KEY] = mcConfig; + + EXPECT_EQ(mcconfig_test, mcconfig_reference); +} + +TEST_F(ConfigurationTest, MemSpec) +{ + std::string_view memspec_string = R"( + { + "memspec": { + "memarchitecturespec": { + "RAACDR": 1, + "RAAIMT": 32, + "RAAMMT": 96, + "burstLength": 16, + "cmdMode": 1, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfChannels": 2, + "nbrOfColumns": 2048, + "nbrOfDIMMRanks": 1, + "nbrOfDevices": 8, + "nbrOfLogicalRanks": 1, + "nbrOfPhysicalRanks": 1, + "nbrOfRanks": 1, + "nbrOfRows": 65536, + "refMode": 1, + "width": 4 + }, + "memoryId": "JEDEC_2x8x2Gbx4_DDR5-3200A", + "memoryType": "DDR5", + "memtimingspec": { + "ACTPDEN": 2, + "CCD_L_WR2_slr": 16, + "CCD_L_WR_slr": 32, + "CCD_L_slr": 8, + "CCD_S_WR_slr": 8, + "CCD_S_slr": 8, + "CCD_WR_dlr": 0, + "CCD_WR_dpr": 0, + "CCD_dlr": 0, + "CPDED": 8, + "FAW_dlr": 0, + "FAW_slr": 32, + "PD": 12, + "PPD": 2, + "PRPDEN": 2, + "RAS": 52, + "RCD": 22, + "RDDQS": 0, + "REFI1": 6240, + "REFI2": 3120, + "REFISB": 1560, + "REFPDEN": 2, + "REFSBRD_dlr": 0, + "REFSBRD_slr": 48, + "RFC1_dlr": 0, + "RFC1_dpr": 0, + "RFC1_slr": 312, + "RFC2_dlr": 0, + "RFC2_dpr": 0, + "RFC2_slr": 208, + "RFCsb_dlr": 0, + "RFCsb_slr": 184, + "RL": 22, + "RP": 22, + "RPRE": 1, + "RPST": 0, + "RRD_L_slr": 8, + "RRD_S_slr": 8, + "RRD_dlr": 0, + "RTP": 12, + "RTRS": 2, + "WL": 20, + "WPRE": 2, + "WPST": 0, + "WR": 48, + "WTR_L": 16, + "WTR_S": 4, + "XP": 12, + "clkMhz": 1600 + } + } + } + )"; + + json_t memspec_reference = json_t::parse(memspec_string); + json_t memspec_test; + memspec_test[MemSpec::KEY] = memSpec; + + EXPECT_EQ(memspec_test, memspec_reference); +} + +TEST_F(ConfigurationTest, AddressMapping) +{ + std::string_view addressmapping_string = R"( + { + "addressmapping": { + "BANKGROUP_BIT": [ + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "BANK_BIT": [ + 13, + 14, + 15 + ], + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "RANK_BIT": [ + 33 + ], + "ROW_BIT": [ + 16 + ] + } + } + )"; + + json_t addressmapping_reference = json_t::parse(addressmapping_string); + json_t addressmapping_test; + addressmapping_test[AddressMapping::KEY] = addressMapping; + + EXPECT_EQ(addressmapping_test, addressmapping_reference); +} + +TEST_F(ConfigurationTest, TraceSetup) +{ + std::string_view tracesetup_string = R"( + { + "tracesetup": [ + { + "clkMhz": 100, + "name": "mytrace.stl" + }, + { + "addressDistribution": "random", + "clkMhz": 100, + "name": "MyTestGen", + "numRequests": 1000, + "rwRatio": 0.5 + }, + { + "clkMhz": 100, + "maxPendingReadRequests": 8, + "name": "MyTestGen", + "states": [ + { + "addressDistribution": "sequential", + "addressIncrement": 256, + "id": 0, + "maxAddress": 1024, + "numRequests": 1000, + "rwRatio": 0.5 + }, + { + "addressDistribution": "sequential", + "addressIncrement": 512, + "id": 1, + "maxAddress": 2048, + "minAddress": 1024, + "numRequests": 100, + "rwRatio": 0.75 + } + ], + "transitions": [ + { + "from": 0, + "probability": 1.0, + "to": 1 + } + ] + }, + { + "clkMhz": 100, + "name": "MyTestHammer", + "numRequests": 4000, + "rowIncrement": 2097152 + } + ] + } + )"; + + json_t tracesetup_reference = json_t::parse(tracesetup_string); + json_t tracesetup_test; + tracesetup_test[TraceSetupConstants::KEY] = traceSetup; + + EXPECT_EQ(tracesetup_test, tracesetup_reference); +} diff --git a/tests/tests_dramsys/AddressDecoderConfigs.h b/tests/tests_dramsys/AddressDecoderConfigs.h new file mode 100644 index 00000000..1b3585cc --- /dev/null +++ b/tests/tests_dramsys/AddressDecoderConfigs.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include + +inline constexpr std::string_view memSpecJsonString = R"( +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 8, + "nbrOfBankGroups": 4, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRows": 65536, + "nbrOfRanks": 1, + "nbrOfDevices": 1, + "nbrOfChannels": 1, + "width": 16, + "per2BankOffset": 8 + }, + "memoryId": "JEDEC_1Gbx16_BG_LPDDR5-6400", + "memoryType": "LPDDR5", + "memtimingspec": { + "RCD_L": 15, + "RCD_S": 15, + "PPD": 2, + "RPab": 17, + "RPpb": 15, + "RAS": 34, + "RCab": 51, + "RCpb": 48, + "FAW": 16, + "RRD": 4, + "RL": 17, + "WCK2CK": 0, + "WCK2DQO": 1, + "RBTP": 4, + "RPRE": 0, + "RPST": 0, + "WL": 9, + "WCK2DQI": 0, + "WPRE": 0, + "WPST": 0, + "WR": 28, + "WTR_L": 10, + "WTR_S": 5, + "CCDMW": 16, + "REFI": 3124, + "REFIpb": 390, + "RFCab": 224, + "RFCpb": 112, + "RTRS": 1, + "BL_n_min_16": 2, + "BL_n_max_16": 4, + "BL_n_L_16": 4, + "BL_n_S_16": 2, + "BL_n_min_32": 6, + "BL_n_max_32": 8, + "BL_n_L_32": 8, + "BL_n_S_32": 2, + "pbR2act": 6, + "pbR2pbR": 72, + "clkMhz": 800 + } + } +} +)"; + +inline constexpr std::string_view addressMappingJsonString = R"( +{ + "addressmapping": { + "BYTE_BIT": [ + 0 + ], + "COLUMN_BIT": [ + 1, + 2, + 3, + 4, + 9, + 10, + 11, + 12, + 13, + 14 + ], + "BANKGROUP_BIT": [ + 5, + 6 + ], + "BANK_BIT": [ + 7, + 8 + ], + "ROW_BIT": [ + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30 + ] + } +} +)"; diff --git a/tests/tests_dramsys/AddressDecoderTests.cpp b/tests/tests_dramsys/AddressDecoderTests.cpp new file mode 100644 index 00000000..b7390555 --- /dev/null +++ b/tests/tests_dramsys/AddressDecoderTests.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2022, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "AddressDecoderConfigs.h" + +#include + +#include +#include + +class AddressDecoderFixture : public ::testing::Test +{ +protected: + AddressDecoderFixture() : + addressMappingJson(nlohmann::json::parse(addressMappingJsonString).at("addressmapping")), + memSpecJson(nlohmann::json::parse(memSpecJsonString).at("memspec")), + addressMappingConfig(addressMappingJson.get()), + memSpec(memSpecConfig), + memSpecConfig(memSpecJson.get()), + addressDecoder(addressMappingConfig, memSpec) + { + } + + nlohmann::json addressMappingJson; + nlohmann::json memSpecJson; + + // Configs + DRAMSys::Config::AddressMapping addressMappingConfig; + DRAMSys::Config::MemSpec memSpecConfig; + + MemSpecLPDDR5 memSpec; + AddressDecoder addressDecoder; +}; + +TEST_F(AddressDecoderFixture, Decoding) +{ + uint64_t address = 0x3A59'1474; + auto decodedAddress = addressDecoder.decodeAddress(address); + + unsigned int channel = decodedAddress.channel; + unsigned int rank = decodedAddress.rank; + unsigned int bankgroup = decodedAddress.bankgroup; + unsigned int bank = decodedAddress.bank; + unsigned int row = decodedAddress.row; + unsigned int column = decodedAddress.column; + unsigned int byte = decodedAddress.byte; + + EXPECT_EQ(channel, 0); + EXPECT_EQ(rank, 0); + EXPECT_EQ(bankgroup, 3); + EXPECT_EQ(bank, 12); + EXPECT_EQ(row, 29874); + EXPECT_EQ(column, 170); + EXPECT_EQ(byte, 0); +} + +TEST_F(AddressDecoderFixture, Encoding) +{ + unsigned int channel = 0; + unsigned int rank = 0; + unsigned int bankgroup = 3; + unsigned int bank = 12; + unsigned int row = 29874; + unsigned int column = 170; + unsigned int byte = 0; + + DecodedAddress decodedAddress(channel, rank, bankgroup, bank, row, column, byte); + + uint64_t address = addressDecoder.encodeAddress(decodedAddress); + EXPECT_EQ(address, 0x3A59'1474); +} + +TEST_F(AddressDecoderFixture, DeEncoding) +{ + std::array testAddresses{std::uint64_t(0x3A59'1474), + std::uint64_t(0x0000'0000), + std::uint64_t(0x2FFA'1231), + std::uint64_t(0x0001'FFFF)}; + + for (auto address: testAddresses) + { + DecodedAddress decodedAddress = addressDecoder.decodeAddress(address); + uint64_t encodedAddress = addressDecoder.encodeAddress(decodedAddress); + + EXPECT_EQ(encodedAddress, address); + } +} \ No newline at end of file diff --git a/tests/tests_dramsys/CommandMuxTests.cpp b/tests/tests_dramsys/CommandMuxTests.cpp deleted file mode 100644 index 146cf86a..00000000 --- a/tests/tests_dramsys/CommandMuxTests.cpp +++ /dev/null @@ -1,110 +0,0 @@ -///* -// * Copyright (c) 2019, Technische Universität Kaiserslautern -// * All rights reserved. -// * -// * Redistribution and use in source and binary forms, with or without -// * modification, are permitted provided that the following conditions are -// * met: -// * -// * 1. Redistributions of source code must retain the above copyright notice, -// * this list of conditions and the following disclaimer. -// * -// * 2. Redistributions in binary form must reproduce the above copyright -// * notice, this list of conditions and the following disclaimer in the -// * documentation and/or other materials provided with the distribution. -// * -// * 3. Neither the name of the copyright holder nor the names of its -// * contributors may be used to endorse or promote products derived from -// * this software without specific prior written permission. -// * -// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER -// * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// * -// * Authors: -// * Lukas Steiner -// */ -// -//#include -//#include -//#include -//#include -// -//#include -//#include -// -//using namespace DRAMSys; -// -//class CommandMuxState -//{ -//public: -// Command firstCommand; -// Command secondCommand; -// Command resultCommand; -//}; -// -//class CommandMuxTestBase : public testing::Test -//{ -//public: -// CommandMux *commandMux; -// -// tlm_generic_payload *firstPayload; -// tlm_generic_payload *secondPayload; -// -// std::pair firstPair; -// std::pair secondPair; -// -// std::vector> readyCommands; -// -// std::pair result; -// -// CommandMuxTestBase() -// { -// commandMux = new CommandMux(); -// firstPayload = new tlm_generic_payload(); -// secondPayload = new tlm_generic_payload(); -// } -// -// ~CommandMuxTestBase() -// { -// delete commandMux; -// delete firstPayload; -// delete secondPayload; -// } -//}; -// -//class CommandMuxTestParam : public CommandMuxTestBase, public testing::WithParamInterface -//{ -//public: -// CommandMuxTestParam() -// { -// commandMux->insertPayload(firstPayload); -// commandMux->insertPayload(secondPayload); -// -// firstPair.first = GetParam().firstCommand; -// firstPair.second = firstPayload; -// secondPair.first = GetParam().secondCommand; -// secondPair.second = secondPayload; -// -// readyCommands.push_back(secondPair); -// readyCommands.push_back(firstPair); -// result = commandMux->selectCommand(readyCommands); -// } -//}; -// -//TEST_P(CommandMuxTestParam, satisfiesCommandOrder) -//{ -// EXPECT_EQ(result.first, GetParam().resultCommand); -//} -// -//INSTANTIATE_TEST_CASE_P(Default, CommandMuxTestParam, testing::Values( -// CommandMuxState{Command::RD, Command::WR, Command::RD}, -// CommandMuxState{Command::RD, Command::ACT, Command::ACT})); diff --git a/tests/tests_dramsys/Testfile.h b/tests/tests_dramsys/Testfile.h index 74835a7d..e381048b 100644 --- a/tests/tests_dramsys/Testfile.h +++ b/tests/tests_dramsys/Testfile.h @@ -1,42 +1,43 @@ -///* -// * Copyright (c) 2019, Technische Universität Kaiserslautern -// * All rights reserved. -// * -// * Redistribution and use in source and binary forms, with or without -// * modification, are permitted provided that the following conditions are -// * met: -// * -// * 1. Redistributions of source code must retain the above copyright notice, -// * this list of conditions and the following disclaimer. -// * -// * 2. Redistributions in binary form must reproduce the above copyright -// * notice, this list of conditions and the following disclaimer in the -// * documentation and/or other materials provided with the distribution. -// * -// * 3. Neither the name of the copyright holder nor the names of its -// * contributors may be used to endorse or promote products derived from -// * this software without specific prior written permission. -// * -// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER -// * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// * -// * Authors: -// * Lukas Steiner -// */ -// -//#include -//#include "../library/src/controller/Command.h" -// -//TEST(testsuite, test) -//{ -// EXPECT_EQ(commandToString(Command::ACT), "ACT"); -//} +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include + +#include + +TEST(testsuite, test) +{ + EXPECT_EQ(Command(Command::Type::ACT).toString(), "ACT"); +} diff --git a/tests/tests_dramsys/b_transport/configs/no_storage.json b/tests/tests_dramsys/b_transport/configs/no_storage.json index c2950e40..6b3be967 100644 --- a/tests/tests_dramsys/b_transport/configs/no_storage.json +++ b/tests/tests_dramsys/b_transport/configs/no_storage.json @@ -1,50 +1,48 @@ { "simulation": { "addressmapping": { - "CONGEN": { - "BANKGROUP_BIT": [ - 28, - 29 - ], - "BANK_BIT": [ - 30, - 31 - ], - "BYTE_BIT": [ - 0, - 1, - 2 - ], - "COLUMN_BIT": [ - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12 - ], - "ROW_BIT": [ - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27 - ] - } + "BANKGROUP_BIT": [ + 28, + 29 + ], + "BANK_BIT": [ + 30, + 31 + ], + "BYTE_BIT": [ + 0, + 1, + 2 + ], + "COLUMN_BIT": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "ROW_BIT": [ + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27 + ] }, "mcconfig": { "Arbiter": "Simple", diff --git a/tests/tests_dramsys/b_transport/configs/storage.json b/tests/tests_dramsys/b_transport/configs/storage.json index 3535eaeb..788056ec 100644 --- a/tests/tests_dramsys/b_transport/configs/storage.json +++ b/tests/tests_dramsys/b_transport/configs/storage.json @@ -1,50 +1,48 @@ { "simulation": { "addressmapping": { - "CONGEN": { - "BANKGROUP_BIT": [ - 28, - 29 - ], - "BANK_BIT": [ - 30, - 31 - ], - "BYTE_BIT": [ - 0, - 1, - 2 - ], - "COLUMN_BIT": [ - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12 - ], - "ROW_BIT": [ - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27 - ] - } + "BANKGROUP_BIT": [ + 28, + 29 + ], + "BANK_BIT": [ + 30, + 31 + ], + "BYTE_BIT": [ + 0, + 1, + 2 + ], + "COLUMN_BIT": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ], + "ROW_BIT": [ + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27 + ] }, "mcconfig": { "Arbiter": "Simple", diff --git a/tests/tests_dramsys/main.cpp b/tests/tests_dramsys/main.cpp index 1c92c82d..42f2dbbe 100644 --- a/tests/tests_dramsys/main.cpp +++ b/tests/tests_dramsys/main.cpp @@ -35,6 +35,7 @@ #include #include +#include "Testfile.h" int sc_main(int argc, char **argv) { diff --git a/tests/tests_regression/compare.sh b/tests/tests_regression/compare.sh index e5262576..859e8044 100755 --- a/tests/tests_regression/compare.sh +++ b/tests/tests_regression/compare.sh @@ -1,7 +1,9 @@ #!/bin/bash -if [[ $(sqldiff ${CMAKE_CURRENT_SOURCE_DIR}/${standard}/expected/${output_filename} ${output_filename}) ]]; then - exit -1 -else - exit 0 -fi +# When comparing the whole database, we do not care if there are differences or not. +# The tables that need to be checked have their own tests. +# The purpose of this script is solely to output the differences of the two databases +# so that they can be inspected easily. + +sqldiff ${CMAKE_CURRENT_SOURCE_DIR}/${standard}/expected/${output_filename} ${output_filename} +exit 0 diff --git a/tests/tests_regression/compare_table.sh b/tests/tests_regression/compare_table.sh index 8978e49d..1e709f07 100755 --- a/tests/tests_regression/compare_table.sh +++ b/tests/tests_regression/compare_table.sh @@ -1,6 +1,9 @@ #!/bin/bash -if [[ $(sqldiff --table ${table} ${CMAKE_CURRENT_SOURCE_DIR}/${standard}/expected/${output_filename} ${output_filename}) ]]; then +stdout=$(sqldiff --table ${table} ${CMAKE_CURRENT_SOURCE_DIR}/${standard}/expected/${output_filename} ${output_filename}) + +if [[ $stdout ]]; then + echo $stdout exit -1 else exit 0 diff --git a/tests/tests_simulator/CMakeLists.txt b/tests/tests_simulator/CMakeLists.txt new file mode 100644 index 00000000..0383d14b --- /dev/null +++ b/tests/tests_simulator/CMakeLists.txt @@ -0,0 +1,27 @@ +############################################### +### tests_simulator ### +############################################### + +cmake_minimum_required(VERSION 3.1.0) + +project(tests_simulator) + +add_executable(${PROJECT_NAME} + main.cpp + cache/tests_cache.cpp + cache/TargetMemory.cpp + cache/ListInitiator.cpp +) + +set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER tests/simulator) + +target_link_libraries(${PROJECT_NAME} PRIVATE + DRAMSys_Simulator + gtest_main +) + +gtest_discover_tests(${PROJECT_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +build_source_group() diff --git a/tests/tests_simulator/cache/ListInitiator.cpp b/tests/tests_simulator/cache/ListInitiator.cpp new file mode 100644 index 00000000..a4e5906a --- /dev/null +++ b/tests/tests_simulator/cache/ListInitiator.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "ListInitiator.h" + +#include +#include +#include +#include +#include +#include +#include + +ListInitiator::ListInitiator(const sc_core::sc_module_name &name, MemoryManager &memoryManager) + : sc_core::sc_module(name), + iSocket("iSocket"), + peq(this, &ListInitiator::peqCallback), + memoryManager(memoryManager) +{ + iSocket.register_nb_transport_bw(this, &ListInitiator::nb_transport_bw); + SC_THREAD(process); +} + +void ListInitiator::process() +{ + for (auto &testTransactionData : testTransactionList) + { + wait(testTransactionData.startTime - sc_core::sc_time_stamp()); + + tlm::tlm_command command = + testTransactionData.command == TestTransactionData::Command::Write + ? tlm::TLM_WRITE_COMMAND + : tlm::TLM_READ_COMMAND; + + auto &trans = memoryManager.allocate(testTransactionData.dataLength); + trans.acquire(); + + TestExtension *ext = new TestExtension(testTransactionData); + trans.set_auto_extension(ext); + + trans.set_command(command); + trans.set_address(testTransactionData.address); + trans.set_data_length(testTransactionData.dataLength); + trans.set_streaming_width(testTransactionData.dataLength); + trans.set_byte_enable_ptr(nullptr); + trans.set_dmi_allowed(false); + trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + if (trans.is_write()) + std::memcpy(trans.get_data_ptr(), &testTransactionData.data, testTransactionData.dataLength); + + if (requestInProgress != nullptr) + { + wait(endRequest); + } + + requestInProgress = &trans; + tlm::tlm_phase phase = tlm::BEGIN_REQ; + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + + std::cout << "\033[1;31m(" << name() << ")@" << std::setfill(' ') << std::setw(12) + << sc_core::sc_time_stamp() << ": " << std::setw(12) + << (command == tlm::TLM_WRITE_COMMAND ? "Write to " : "Read from ") + << "Addr = " << std::setfill('0') << std::setw(8) << std::dec + << testTransactionData.address << " Data = " + << "0x" << std::setfill('0') << std::setw(8) << std::hex + << testTransactionData.data << "(nb_transport) \033[0m" << std::endl; + + tlm::tlm_sync_enum status = iSocket->nb_transport_fw(trans, phase, delay); + + if (status == tlm::TLM_UPDATED) + { + peq.notify(trans, phase, delay); + } + else if (status == tlm::TLM_COMPLETED) + { + requestInProgress = nullptr; + checkTransaction(trans); + trans.release(); + } + } +} + +tlm::tlm_sync_enum ListInitiator::nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &delay) +{ + peq.notify(trans, phase, delay); + return tlm::TLM_ACCEPTED; +} + +void ListInitiator::peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase) +{ + if (phase == tlm::END_REQ || (&trans == requestInProgress && phase == tlm::BEGIN_RESP)) + { + requestInProgress = nullptr; + endRequest.notify(); + } + else if (phase == tlm::BEGIN_REQ || phase == tlm::END_RESP) + { + SC_REPORT_FATAL(name(), "Illegal transaction phase received"); + } + + if (phase == tlm::BEGIN_RESP) + { + checkTransaction(trans); + + tlm::tlm_phase fw_phase = tlm::END_RESP; + sc_core::sc_time delay = sc_core::sc_time(1, sc_core::SC_NS); + iSocket->nb_transport_fw(trans, fw_phase, delay); + + trans.release(); + } +} + +void ListInitiator::checkTransaction(tlm::tlm_generic_payload &trans) +{ + if (trans.is_response_error()) + { + SC_REPORT_ERROR(name(), "Transaction returned with error!"); + } + + tlm::tlm_command command = trans.get_command(); + + uint64_t transData{}; + + if (trans.get_data_length() == 1) + transData = *reinterpret_cast(trans.get_data_ptr()); + else if (trans.get_data_length() == 2) + transData = *reinterpret_cast(trans.get_data_ptr()); + else if (trans.get_data_length() == 4) + transData = *reinterpret_cast(trans.get_data_ptr()); + else if (trans.get_data_length() == 8) + transData = *reinterpret_cast(trans.get_data_ptr()); + + TestExtension *ext = nullptr; + trans.get_extension(ext); + TestTransactionData data = ext->getTestData(); + + std::cout << "\033[1;31m(" << name() << ")@" << std::setfill(' ') << std::setw(12) + << sc_core::sc_time_stamp() << ": " << std::setw(12) + << (command == tlm::TLM_WRITE_COMMAND ? "Check Write " : "Check Read ") + << "Addr = " << std::setfill('0') << std::setw(8) << std::dec << data.address + << " Data = " + << "0x" << std::setfill('0') << std::setw(8) << std::hex << transData << "\033[0m" + << std::endl; + + if (data.expectedEndTime != sc_core::sc_time_stamp()) + { + SC_REPORT_FATAL(name(), "NOT EXPECTED TIME"); + } + + if (trans.is_read() && data.data != transData) + { + SC_REPORT_FATAL(name(), "NOT EXPECTED DATA"); + } +} diff --git a/tests/tests_simulator/cache/ListInitiator.h b/tests/tests_simulator/cache/ListInitiator.h new file mode 100644 index 00000000..860975cd --- /dev/null +++ b/tests/tests_simulator/cache/ListInitiator.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "simulator/MemoryManager.h" + +#include +#include + +class ListInitiator : public sc_core::sc_module +{ +public: + tlm_utils::simple_initiator_socket iSocket; + + SC_HAS_PROCESS(ListInitiator); + ListInitiator(const sc_core::sc_module_name &name, MemoryManager &memoryManager); + + struct TestTransactionData + { + sc_core::sc_time startTime; + sc_core::sc_time expectedEndTime; + + enum class Command + { + Read, + Write, + } command; + + uint64_t address; + uint32_t dataLength; + uint64_t data; + }; + + void appendTestTransactionList(const std::vector &testTransactionList) + { + std::copy(testTransactionList.cbegin(), testTransactionList.cend(), std::back_inserter(this->testTransactionList)); + } + +private: + class TestExtension : public tlm::tlm_extension + { + public: + TestExtension(TestTransactionData data) : data(std::move(data)) {} + + tlm_extension_base *clone() const { return new TestExtension(data); } + + void copy_from(const tlm_extension_base &ext) + { + const TestExtension &cpyFrom = static_cast(ext); + data = cpyFrom.getTestData(); + } + + TestTransactionData getTestData() const { return data; } + + private: + TestTransactionData data; + }; + + void process(); + + tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &delay); + void peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase); + void checkTransaction(tlm::tlm_generic_payload &trans); + + std::vector testTransactionList; + + sc_core::sc_event endRequest; + tlm_utils::peq_with_cb_and_phase peq; + tlm::tlm_generic_payload *requestInProgress = nullptr; + MemoryManager &memoryManager; +}; diff --git a/tests/tests_simulator/cache/TargetMemory.cpp b/tests/tests_simulator/cache/TargetMemory.cpp new file mode 100644 index 00000000..bc1524a6 --- /dev/null +++ b/tests/tests_simulator/cache/TargetMemory.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "TargetMemory.h" + +#include +#include +#include +#include + +DECLARE_EXTENDED_PHASE(INTERNAL); + +TargetMemory::TargetMemory(const sc_core::sc_module_name &name, + sc_core::sc_time acceptDelay, + sc_core::sc_time memoryLatency, + std::size_t bufferSize) + : sc_core::sc_module(name), + tSocket("tSocket"), + bufferSize(bufferSize), + peq(this, &TargetMemory::peqCallback), + acceptDelay(acceptDelay), + memoryLatency(memoryLatency) +{ + tSocket.register_nb_transport_fw(this, &TargetMemory::nb_transport_fw); + + memory.reserve(SIZE); + std::fill(memory.begin(), memory.end(), 0); +} + +tlm::tlm_sync_enum TargetMemory::nb_transport_fw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &delay) +{ + peq.notify(trans, phase, delay); + return tlm::TLM_ACCEPTED; +} + +void TargetMemory::printBuffer(int max, int n) +{ + std::cout << "\033[1;35m(" << name() << ")@" << std::setfill(' ') << std::setw(12) + << sc_core::sc_time_stamp() << " Target Buffer: " + << "["; + for (int i = 0; i < n; i++) + { + std::cout << "█"; + } + for (int i = 0; i < max - n; i++) + { + std::cout << " "; + } + std::cout << "]" + << " (Max:" << max << ") " + << "\033[0m" << std::endl; + std::cout.flush(); +} + +void TargetMemory::peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase) +{ + sc_core::sc_time delay; + + if (phase == tlm::BEGIN_REQ) + { + trans.acquire(); + + if (currentTransactions < bufferSize) + { + sendEndRequest(trans); + } + else + { + endRequestPending = &trans; + } + } + else if (phase == tlm::END_RESP) + { + if (!responseInProgress) + { + SC_REPORT_FATAL(name(), "Illegal transaction phase END_RESP received by target"); + } + + currentTransactions--; + printBuffer(bufferSize, currentTransactions); + + responseInProgress = false; + if (!responseQueue.empty()) + { + tlm::tlm_generic_payload *next = responseQueue.front(); + responseQueue.pop(); + sendResponse(*next); + } + + if (endRequestPending != nullptr) + { + sendEndRequest(*endRequestPending); + endRequestPending = nullptr; + } + } + else if (phase == INTERNAL) + { + executeTransaction(trans); + + if (responseInProgress) + { + responseQueue.push(&trans); + } + else + { + sendResponse(trans); + } + } + else // tlm::END_REQ or tlm::BEGIN_RESP + { + SC_REPORT_FATAL(name(), "Illegal transaction phase received"); + } +} + +void TargetMemory::sendEndRequest(tlm::tlm_generic_payload &trans) +{ + tlm::tlm_phase bw_phase; + sc_core::sc_time delay; + + // Queue the acceptance and the response with the appropriate latency + bw_phase = tlm::END_REQ; + delay = acceptDelay; + + tlm::tlm_sync_enum status = tSocket->nb_transport_bw(trans, bw_phase, delay); + + // Queue internal event to mark beginning of response + delay = delay + memoryLatency; // MEMORY Latency + peq.notify(trans, INTERNAL, delay); + + currentTransactions++; + printBuffer(bufferSize, currentTransactions); +} + +void TargetMemory::sendResponse(tlm::tlm_generic_payload &trans) +{ + sc_assert(responseInProgress == false); + + responseInProgress = true; + tlm::tlm_phase bw_phase = tlm::BEGIN_RESP; + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + tlm::tlm_sync_enum status = tSocket->nb_transport_bw(trans, bw_phase, delay); + + if (status == tlm::TLM_UPDATED) + { + peq.notify(trans, bw_phase, delay); + } + else if (status == tlm::TLM_COMPLETED) + { + SC_REPORT_FATAL(name(), "This transition is deprecated since TLM2.0.1"); + } + + trans.release(); +} + +void TargetMemory::executeTransaction(tlm::tlm_generic_payload &trans) +{ + tlm::tlm_command command = trans.get_command(); + sc_dt::uint64 address = trans.get_address(); + unsigned char *data_ptr = trans.get_data_ptr(); + unsigned int data_length = trans.get_data_length(); + unsigned char *byte_enable_ptr = trans.get_byte_enable_ptr(); + unsigned int streaming_width = trans.get_streaming_width(); + + if (address >= SIZE - 64) + { + trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE); + return; + } + if (byte_enable_ptr != nullptr) + { + trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); + return; + } + if (data_length > 64 || streaming_width < data_length) + { + trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); + return; + } + + if (command == tlm::TLM_READ_COMMAND) + { + std::memcpy(trans.get_data_ptr(), &memory[trans.get_address()], trans.get_data_length()); + } + else if (command == tlm::TLM_WRITE_COMMAND) + { + memcpy(&memory[trans.get_address()], trans.get_data_ptr(), trans.get_data_length()); + } + + std::cout << "\033[1;32m(" << name() << ")@" << std::setfill(' ') << std::setw(12) + << sc_core::sc_time_stamp() << ": " << std::setw(12) + << (command == tlm::TLM_WRITE_COMMAND ? "Exec. Write " : "Exec. Read ") + << "Addr = " << std::setfill('0') << std::setw(8) << std::dec << address << " Data = " + << "0x" << std::setfill('0') << std::setw(8) << std::hex + << *reinterpret_cast(data_ptr) << "\033[0m" << std::endl; + + trans.set_response_status(tlm::TLM_OK_RESPONSE); +} diff --git a/tests/tests_simulator/cache/TargetMemory.h b/tests/tests_simulator/cache/TargetMemory.h new file mode 100644 index 00000000..5ec280d5 --- /dev/null +++ b/tests/tests_simulator/cache/TargetMemory.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#pragma once + +#include +#include +#include +#include + +#include + +class TargetMemory : public sc_core::sc_module +{ +public: + tlm_utils::simple_target_socket tSocket; + SC_HAS_PROCESS(TargetMemory); + TargetMemory(const sc_core::sc_module_name &name, + sc_core::sc_time acceptDelay, + sc_core::sc_time memoryLatency, + std::size_t bufferSize = DEFAULT_BUFFER_SIZE); + +private: + tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &delay); + + void peqCallback(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase); + + void sendEndRequest(tlm::tlm_generic_payload &trans); + void sendResponse(tlm::tlm_generic_payload &trans); + void executeTransaction(tlm::tlm_generic_payload &trans); + + void printBuffer(int max, int n); + + static constexpr std::size_t SIZE = static_cast(64 * 1024); + static constexpr std::size_t DEFAULT_BUFFER_SIZE = 8; + const std::size_t bufferSize; + + const sc_core::sc_time acceptDelay; + const sc_core::sc_time memoryLatency; + + std::vector memory; + + unsigned int currentTransactions = 0; + bool responseInProgress = false; + tlm::tlm_generic_payload *endRequestPending = nullptr; + + tlm_utils::peq_with_cb_and_phase peq; + std::queue responseQueue; +}; diff --git a/tests/tests_simulator/cache/tests_cache.cpp b/tests/tests_simulator/cache/tests_cache.cpp new file mode 100644 index 00000000..44d59737 --- /dev/null +++ b/tests/tests_simulator/cache/tests_cache.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Derek Christ + */ + +#include "ListInitiator.h" +#include "TargetMemory.h" + +#include +#include + +#include + +class SystemCTest : public testing::Test +{ +public: + ~SystemCTest() override { sc_core::sc_get_curr_simcontext()->reset(); } +}; + +class DirectMappedCache : public SystemCTest +{ +protected: + DirectMappedCache() + : memoryManager(true), + initiator("ListInitiator", memoryManager), + target("TargetMemory", + sc_core::sc_time(1, sc_core::SC_NS), + sc_core::sc_time(10, sc_core::SC_NS)), + cache("Cache", + 32768, + 1, + 32, + 8, + 8, + 8, + true, + sc_core::sc_time(1, sc_core::SC_NS), + 5, + memoryManager) + { + initiator.iSocket.bind(cache.tSocket); + cache.iSocket.bind(target.tSocket); + } + + MemoryManager memoryManager; + ListInitiator initiator; + TargetMemory target; + Cache cache; +}; + +TEST_F(DirectMappedCache, Basic) +{ + using sc_core::SC_NS; + using sc_core::sc_time; + using Command = ListInitiator::TestTransactionData::Command; + + std::vector list{ + // Test miss + {sc_time(0, SC_NS), sc_time(17, SC_NS), Command::Read, 0x0, 4, 0x0}, + + // Test secondary miss + {sc_time(1, SC_NS), sc_time(18, SC_NS), Command::Read, 0x0, 4, 0x0}, + + // Test hit + {sc_time(100, SC_NS), sc_time(106, SC_NS), Command::Read, 0x0, 4, 0x0}, + + // Test write hit + {sc_time(200, SC_NS), sc_time(206, SC_NS), Command::Write, 0x0, 4, 0x8}, + + // Test eviction + {sc_time(300, SC_NS), sc_time(317, SC_NS), Command::Write, 1024 * 32, 4, 0x0}}; + + initiator.appendTestTransactionList(list); + sc_core::sc_start(); +} + +// Does not work yet +// Unclear if a snoop should even happen when the line eviction fails +// TEST_F(DirectMappedCache, WriteBufferSnooping) +// { +// using sc_core::SC_NS; +// using sc_core::sc_time; +// using Command = ListInitiator::TestTransactionData::Command; + +// std::vector list{ +// // Allocate line +// {sc_time(0, SC_NS), sc_time(17, SC_NS), Command::Write, 0x0, 4, 0x0}, + +// // Evict line +// {sc_time(100, SC_NS), sc_time(117, SC_NS), Command::Read, 1024 * 32, 4, 0x0}, + +// // Snoop from write buffer +// {sc_time(102, SC_NS), sc_time(108, SC_NS), Command::Read, 0x0, 4, 0x0}, +// }; + +// initiator.appendTestTransactionList(list); +// sc_core::sc_start(); +// } diff --git a/tests/tests_simulator/main.cpp b/tests/tests_simulator/main.cpp new file mode 100644 index 00000000..1c92c82d --- /dev/null +++ b/tests/tests_simulator/main.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include +#include + +int sc_main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}