@@ -9,7 +9,9 @@ import "simics/devs/signal.dml";
9
9
import "simics/devs/ram.dml";
10
10
import "simics/devs/memory-space.dml";
11
11
import "simics/devs/translator.dml";
12
+ import "simics/model-iface/direct-memory.dml";
12
13
import "simics/model-iface/transaction.dml";
14
+ import "simics/simulator/conf-object.dml";
13
15
14
16
template _reg_or_field {
15
17
param is_register : bool;
@@ -1393,6 +1395,141 @@ template map_target is (connect, _qname) {
1393
1395
}
1394
1396
}
1395
1397
1398
+ /**
1399
+ ### ram
1400
+
1401
+ This template can be instantiated on a `port`, `device`, `bank` or
1402
+ `subdevice` object for an efficient implementation of a private RAM
1403
+ area. This is implemented by automatically creating a separate Simics object
1404
+ of class `ram`, with an image attached to it, and using the `direct_memory`
1405
+ interface to access the image efficiently. This gives a small memory
1406
+ footprint and efficient checkpointing; this can make a visible impact for
1407
+ internal memories that are several megabytes in size.
1408
+
1409
+ Requires a single integer parameter `size`, which must be set to a multiple of 8192.
1410
+
1411
+ Provides the following methods:
1412
+ */
1413
+ typedef struct {
1414
+ direct_memory_handle_t handle;
1415
+ uint8 *data;
1416
+ } _ram_page_t;
1417
+ template ram {
1418
+ param size;
1419
+ connect ram is (init_as_subobj, destroy) {
1420
+ param documentation = "dm";
1421
+ interface direct_memory;
1422
+ interface ram;
1423
+ param page_size = 8192;
1424
+ param size = parent.size;
1425
+ #if (size % page_size != 0) { error "size must be a multiple of 8192"; }
1426
+ param classname = "ram";
1427
+ session _ram_page_t pages[size / page_size];
1428
+ method init() {
1429
+ default();
1430
+ SIM_set_attribute_default(this.obj, "image", SIM_make_attr_nil());
1431
+ SIM_set_attribute_default(
1432
+ this.obj, "self_allocated_image_size", SIM_make_attr_uint64(size));
1433
+ }
1434
+
1435
+ method invalidate(direct_memory_handle_t handle) {
1436
+ local int page = cast(direct_memory.get_user_data(handle), uintptr_t);
1437
+ pages[page].data = NULL;
1438
+ }
1439
+ method request(uint64 offs) -> (uint8 *) {
1440
+ local int page = offs / page_size;
1441
+ if (pages[page].data == NULL) {
1442
+ if (pages[page].handle == NULL) {
1443
+ pages[page].handle = direct_memory.get_handle(
1444
+ parent.obj, 0, page * page_size, page_size);
1445
+ direct_memory.set_user_data(
1446
+ pages[page].handle, cast(cast(page, uintptr_t), void *));
1447
+ }
1448
+ local direct_memory_t mem = direct_memory.request(
1449
+ pages[page].handle, Sim_Access_Read | Sim_Access_Write,
1450
+ Sim_Access_Read | Sim_Access_Write | Sim_Access_Execute);
1451
+ pages[page].data = mem.data;
1452
+ }
1453
+ return pages[page].data + offs % page_size;
1454
+ }
1455
+
1456
+ method destroy() {
1457
+ for (local int i = 0; i < pages.len; i++) {
1458
+ if (pages[i].handle != NULL) {
1459
+ direct_memory.release(pages[i].handle);
1460
+ }
1461
+ }
1462
+ }
1463
+ }
1464
+
1465
+ /**
1466
+ * `get_u8(int64 offs) -> (uint8)`
1467
+
1468
+ Return a single byte from a given offset.
1469
+ */
1470
+ method get_u8(uint64 offs) -> (uint8) {
1471
+ assert offs < ram.size;
1472
+ return *ram.request(offs);
1473
+ }
1474
+ /**
1475
+ * `get_u8(int64 offs) -> (uint8)`
1476
+
1477
+ Read a 64-bit little-endian integer from a given offset
1478
+ */
1479
+ method get_u64_le(uint64 offs) -> (uint64) {
1480
+ assert offs + 7 < ram.size;
1481
+ if ((offs & ram.page_size) != ((offs + 7) & ram.page_size)) {
1482
+ local uint8 ret[8];
1483
+ local uint64 split = 8 - (offs & 7);
1484
+ memcpy(ret, ram.request(offs), split);
1485
+ memcpy(ret + split, ram.request(offs + split), 8 - split);
1486
+ return *cast(ret, uint64_le_t *);
1487
+ } else {
1488
+ return *cast(ram.request(offs), uint64_le_t *);
1489
+ }
1490
+ }
1491
+ /**
1492
+ * `set_u8(int64 offs) -> (uint8)`
1493
+
1494
+ Update a single byte at a given offset.
1495
+ */
1496
+ method set_u8(uint64 offs, uint8 val) {
1497
+ assert offs < ram.size;
1498
+ *ram.request(offs) = val;
1499
+ }
1500
+
1501
+ implement direct_memory_update {
1502
+ method release(conf_object_t *target, direct_memory_handle_t handle,
1503
+ direct_memory_ack_id_t id) {
1504
+ assert target == ram.obj;
1505
+ ram.invalidate(handle);
1506
+ local int page = cast(
1507
+ ram.direct_memory.get_user_data(handle), uintptr_t);
1508
+ ram.pages[page].handle = NULL;
1509
+ ram.direct_memory.ack(id);
1510
+ }
1511
+ method update_permission(conf_object_t *target,
1512
+ direct_memory_handle_t handle,
1513
+ access_t lost_access,
1514
+ access_t lost_permission,
1515
+ access_t lost_inhibit,
1516
+ direct_memory_ack_id_t id) {
1517
+ assert target == ram.obj;
1518
+ ram.invalidate(handle);
1519
+ ram.direct_memory.ack(id);
1520
+ }
1521
+ method conflicting_access(conf_object_t *target,
1522
+ direct_memory_handle_t handle,
1523
+ access_t conflicting_permission,
1524
+ direct_memory_ack_id_t id) {
1525
+ assert target == ram.obj;
1526
+ ram.invalidate(handle);
1527
+ ram.direct_memory.ack(id);
1528
+ }
1529
+ }
1530
+ }
1531
+
1532
+
1396
1533
/**
1397
1534
## Signal related templates
1398
1535
0 commit comments