@@ -9,7 +9,9 @@ import "simics/devs/signal.dml";
99import "simics/devs/ram.dml";
1010import "simics/devs/memory-space.dml";
1111import "simics/devs/translator.dml";
12+ import "simics/model-iface/direct-memory.dml";
1213import "simics/model-iface/transaction.dml";
14+ import "simics/simulator/conf-object.dml";
1315
1416template _reg_or_field {
1517 param is_register : bool;
@@ -1393,6 +1395,141 @@ template map_target is (connect, _qname) {
13931395 }
13941396}
13951397
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+
13961533/**
13971534## Signal related templates
13981535
0 commit comments