forked from chipsalliance/riscv-dv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
riscv_load_store_instr_lib.py
339 lines (303 loc) · 15.1 KB
/
riscv_load_store_instr_lib.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import random
import logging
import vsc
from enum import IntEnum, auto
from pygen_src.riscv_directed_instr_lib import riscv_mem_access_stream
from pygen_src.riscv_instr_pkg import riscv_reg_t, riscv_instr_name_t, riscv_instr_group_t
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.target.rv32i import riscv_core_setting as rcs
from pygen_src.isa.riscv_instr import riscv_instr
class locality_e(IntEnum):
NARROW = 0
HIGH = auto()
MEDIUM = auto()
SPARSE = auto()
@vsc.randobj
class riscv_load_store_base_instr_stream(riscv_mem_access_stream):
def __init__(self):
super().__init__()
self.num_load_store = vsc.rand_uint32_t()
self.num_mixed_instr = vsc.rand_uint32_t()
self.base = vsc.rand_int32_t()
self.offset = []
self.addr = []
self.load_store_instr = []
self.data_page_id = vsc.rand_uint32_t()
print("Load Constructor data_page_id = ", self.data_page_id)
self.rs1_reg = vsc.rand_enum_t(riscv_reg_t)
self.dummy = []
self.locality = vsc.rand_enum_t(locality_e)
self.max_load_store_offset = vsc.rand_int32_t()
self.use_sp_as_rs1 = vsc.rand_bit_t()
@vsc.constraint
def sp_rnd_order_c(self):
vsc.solve_order(self.use_sp_as_rs1, self.rs1_reg)
@vsc.constraint
def sp_c(self):
vsc.dist(self.use_sp_as_rs1, [vsc.weight(1, 1), vsc.weight(0, 2)])
if self.use_sp_as_rs1:
self.rs1_reg == riscv_reg_t.SP
"""
@vsc.constraint
def rs1_c(self):
self.rs1_reg.not_inside(vsc.rangelist(cfg.reserved_regs,
self.reserved_rd, riscv_reg_t.ZERO))
"""
@vsc.constraint
def addr_c(self):
vsc.solve_order(self.data_page_id, self.max_load_store_offset)
vsc.solve_order(self.max_load_store_offset, self.base)
# TODO
self.data_page_id < self.max_data_page_id
'''with vsc.foreach(self.data_page, idx=True) as i:
if i == self.data_page_id:
self.max_load_store_offset == self.data_page[i]['size_in_bytes']'''
self.base in vsc.rangelist(vsc.rng(0, self.max_load_store_offset - 1))
def randomize_offset(self):
addr_ = vsc.rand_int32_t()
offset_ = vsc.rand_int32_t()
self.offset = [0] * self.num_load_store
self.addr = [0] * self.num_load_store
for i in range(self.num_load_store):
"""
try:
# TODO Randomization for addr_
# vsc.randomize(addr_)
# print("Addr_ ", addr_)
with vsc.randomize_with(addr_, offset_):
if self.locality == locality_e.NARROW:
offset_.inside(vsc.rangelist(vsc.rng(-16,16)))
elif self.locality == locality_e.HIGH:
offset_.inside(vsc.rangelist(vsc.rng(-64,64)))
elif self.locality == locality_e.MEDIUM:
offset_.inside(vsc.rangelist(vsc.rng(-256,256)))
elif self.locality == locality_e.SPARSE:
offset_.inside(vsc.rangelist(vsc.rng(-2048,2047)))
# print("offset_ ", offset_)
# print("Base ", self.base)
var1 = self.base + offset_.get_val() - 1
var2 = self.base + offset_.get_val() + 1
addr_.inside(vsc.rangelist(vsc.rng(var1, var2)))
print("Addr_ ", addr_)
# addr_ == self.base + offset_
# addr_ == 100
except Exception:
logging.critical("Cannot randomize load/store offset")
"""
try:
# TODO Randomization for addr_
# vsc.randomize(addr_)
# print("Addr_ ", addr_)
if self.locality == locality_e.NARROW:
offset_ = random.randrange(-16, 16)
elif self.locality == locality_e.HIGH:
offset_ = random.randrange(-64, 64)
elif self.locality == locality_e.MEDIUM:
offset_ = random.randrange(-256, 256)
elif self.locality == locality_e.SPARSE:
offset_ = random.randrange(-2048, 2047)
# print("offset_ ", offset_)
# print("Base ", self.base)
var1 = self.base + offset_ - 1
var2 = self.base + offset_ + 1
addr_ = random.randrange(var1, var2)
#print("Addr_ ", addr_)
# addr_ == self.base + offset_
# addr_ == 100
except Exception:
logging.critical("Cannot randomize load/store offset")
# print("Addr_ after if ", addr_)
self.offset[i] = offset_
self.addr[i] = addr_
def pre_randomize(self):
logging.info("max_load_store_offset: %d", self.max_load_store_offset)
logging.info("Base: %d", self.base)
super().pre_randomize()
if(riscv_reg_t.SP in [cfg.reserved_regs, self.reserved_rd]):
self.use_sp_as_rs1 = 0
with vsc.raw_mode():
self.use_sp_as_rs1.rand_mode = False
self.sp_rnd_order_c.constraint_mode(False)
def post_randomize(self):
logging.info("max_load_store_offset: %d", self.max_load_store_offset)
logging.info("Base: %d", self.base)
self.randomize_offset()
if(not(self.rs1_reg in [self.reserved_rd])):
self.reserved_rd.append(self.rs1_reg)
self.gen_load_store_instr()
self.add_mixed_instr(self.num_mixed_instr)
self.add_rs1_init_la_instr(self.rs1_reg, self.data_page_id, 2657) # made chnage
super().post_randomize()
# Generate each load/store instruction
def gen_load_store_instr(self):
allowed_instr = []
enable_compressed_load_store = 0
self.randomize_avail_regs()
if((self.rs1_reg in [riscv_reg_t.S0, riscv_reg_t.S1, riscv_reg_t.A0, riscv_reg_t.A1,
riscv_reg_t.A2, riscv_reg_t.A3, riscv_reg_t.A4, riscv_reg_t.A5, riscv_reg_t.SP]) and # TODO
not(cfg.disable_compressed_instr)):
enable_compressed_load_store = 1 # made change
for i in range(len(self.addr)):
# Assign the allowed load/store instructions based on address alignment
# This is done separately rather than a constraint to improve the randomization performance
allowed_instr.extend(
[riscv_instr_name_t.LB.name, riscv_instr_name_t.LBU.name, riscv_instr_name_t.SB.name])
if(not cfg.enable_unaligned_load_store):
if(self.addr[i] == 0):
allowed_instr.extend(
[riscv_instr_name_t.LH.name, riscv_instr_name_t.LHU.name, riscv_instr_name_t.SH.name])
if(self.addr[i] % 4 == 0):
allowed_instr.extend([riscv_instr_name_t.LW.name, riscv_instr_name_t.SW.name])
if(cfg.enable_floating_point):
allowed_instr.extend([riscv_instr_name_t.FLW.name,
riscv_instr_name_t.FSW.name])
if((self.offset[i] in range(128)) and (self.offset[i] % 4 == 0) and
(riscv_instr_group_t.RV32C in rcs.supported_isa) and
(enable_compressed_load_store)):
if(self.rs1_reg == riscv_reg_t.SP):
logging.info("Add LWSP/SWSP to allowed instr")
allowed_instr.extend(
[riscv_instr_name_t.C_LWSP.name, riscv_instr_name_t.C_SWSP.name])
else:
allowed_instr.extend(
[riscv_instr_name_t.C_LW.name, riscv_instr_name_t.C_SW.name])
if(cfg.enable_floating_point and riscv_instr_group_t.RV32FC in rcs.supported_isa):
allowed_instr.extend(
[riscv_instr_name_t.C_FLW.name, riscv_instr_name_t.C_FSW.name])
if((rcs.XLEN >= 64) and (self.addr[i] % 8 == 0)): # made chnages
allowed_instr.extend([riscv_instr_name_t.LWU.name,
riscv_instr_name_t.LD.name, riscv_instr_name_t.SD.name])
if(cfg.enable_floating_point and (riscv_instr_group_t.RV32D in rcs.supported_isa)):
allowed_instr.extend([riscv_instr_name_t.FLD.name,
riscv_instr_name_t.FSD.name])
if((self.offset[i] in range(256)) and (self.offset[i] % 8 == 0) and
(riscv_instr_group_t.RV64C in rcs.supported_isa) and
enable_compressed_load_store):
if(self.rs1_reg == riscv_reg_t.SP):
allowed_instr.extend(
[riscv_instr_name_t.C_LDSP.name, riscv_instr_name_t.C_SDSP.name])
else:
allowed_instr.extend(
[riscv_instr_name_t.C_LD.name, riscv_instr_name_t.C_SD.name])
if(cfg.enable_floating_point and (riscv_instr_group_t.RV32DC in rcs.supported_isa)):
allowed_instr.extend(
[riscv_instr_name_t.C_FLD.name, riscv_instr_name_t.C_FSD.name])
else: # unalligned load/store
allowed_instr.extend([riscv_instr_name_t.LW.name, riscv_instr_name_t.SW.name, riscv_instr_name_t.LH.name,
riscv_instr_name_t.LHU.name, riscv_instr_name_t.SH.name])
# Compressed load/store still needs to be alligned
if((self.offset[i] in range(128)) and (self.offset[i] % 4 == 0) and
(riscv_instr_group_t.RV32C in rcs.supported_isa) and
enable_compressed_load_store):
if(self.rs1_reg == riscv_reg_t.SP):
allowed_instr.extend(
[riscv_instr_name_t.C_LWSP.name, riscv_instr_name_t.C_SWSP.name])
else:
allowed_instr.extend(
[riscv_instr_name_t.C_LW.name, riscv_instr_name_t.C_SW.name])
if(rcs.XLEN >= 64):
allowed_instr.extend(
[riscv_instr_name_t.LWU.name, riscv_instr_name_t.LD.name, riscv_instr_name_t.SD.name])
if((self.offset[i] in range(256)) and (self.offset[i] % 8 == 0) and
(riscv_instr_group_t.RV64C in rcs.supported_isa) and
enable_compressed_load_store):
if(self.rs1_reg == riscv_reg_t.SP):
allowed_instr.extend(
[riscv_instr_name_t.C_LWSP.name, riscv_instr_name_t.C_SWSP.name])
else:
allowed_instr.extend(
[riscv_instr_name_t.C_LD.name, riscv_instr_name_t.C_SD.name])
instr = riscv_instr.get_load_store_instr(allowed_instr)
instr.has_rs1 = 0
instr.has_imm = 0
self.randomize_gpr(instr)
instr.rs1 = self.rs1_reg
instr.imm_str = str(instr.uintToInt(self.offset[i]))
instr.process_load_store = 0
self.instr_list.append(instr)
self.load_store_instr.append(instr)
@vsc.randobj
class riscv_single_load_store_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
super().__init__()
@vsc.constraint
def legal_c(self):
self.num_load_store == 1
self.num_mixed_instr < 5
@vsc.randobj
class riscv_load_store_stress_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
super().__init__()
self.max_instr_cnt = 30
self.min_instr_cnt = 10
@vsc.constraint
def legal_c(self):
self.num_load_store.inside(vsc.rangelist(vsc.rng(self.min_instr_cnt, self.max_instr_cnt)))
self.num_mixed_instr == 0
@vsc.randobj
class riscv_load_store_rand_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
super().__init__()
@vsc.constraint
def legal_c(self):
self.num_load_store.inside(vsc.rangelist(vsc.rng(10, 30)))
self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(10, 30)))
@vsc.randobj
class riscv_load_store_hazard_instr_stream(riscv_load_store_base_instr_stream):
def __init__(self):
super().__init__()
self.hazard_ratio = vsc.rand_int32_t()
@vsc.constraint
def hazard_ratio_c(self):
self.hazard_ratio.inside(vsc.rangelist(vsc.rng(20, 100)))
@vsc.constraint
def legal_c(self):
self.num_load_store.inside(vsc.rangelist(vsc.rng(10, 20)))
self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(1, 7)))
def randomize_offset(self):
addr_ = vsc.rand_int32_t()
offset_ = vsc.rand_int32_t()
self.offset = [0] * self.num_load_store
self.addr = [0] * self.num_load_store
rand_num = random.randrange(0, 100)
for i in range(self.num_load_store):
if((i > 0) and (rand_num < self.hazard_ratio)):
self.offset[i] = self.offset[i - 1]
self.addr[i] = self.addr[i - 1]
else:
try:
# TODO Randomization for addr_
# vsc.randomize(addr_)
# print("Addr_ ", addr_)
if self.locality == locality_e.NARROW:
offset_ = random.randrange(-16, 16)
elif self.locality == locality_e.HIGH:
offset_ = random.randrange(-64, 64)
elif self.locality == locality_e.MEDIUM:
offset_ = random.randrange(-256, 256)
elif self.locality == locality_e.SPARSE:
offset_ = random.randrange(-2048, 2047)
# print("offset_ ", offset_)
# print("Base ", self.base)
var1 = self.base + offset_ - 1
var2 = self.base + offset_ + 1
addr_ = random.randrange(var1, var2)
#print("Addr_ ", addr_)
# addr_ == self.base + offset_
# addr_ == 100
except Exception:
logging.critical("Cannot randomize load/store offset")
# print("Addr_ after if ", addr_)
self.offset[i] = offset_
self.addr[i] = addr_