Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASENOTES-1.4.docu
Original file line number Diff line number Diff line change
Expand Up @@ -521,4 +521,6 @@
This fix is only enabled by default with Simics API version 7 or above.
With version 6 or below it must be explicitly enabled by passing
<tt>--no-compat=shared_logs_on_device</tt> to DMLC.</add-note></build-id>
<build-id _6="next" _7="next"><add-note> Improved the run-time performance
of accesses to registers with many fields.</add-note></build-id>
</rn>
126 changes: 40 additions & 86 deletions lib/1.4/dml-builtins.dml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import "simics/model-iface/register-view.dml";
import "simics/model-iface/register-view-read-only.dml";
import "simics/model-iface/transaction.dml";
import "simics/util/hashtab.dml";
import "simics/util/bitcount.dml";

import "simics/simulator/python.dml";
import "simics/simulator/sim-get-class.dml";
Expand Down Expand Up @@ -2825,136 +2826,89 @@ template register is (_conf_attribute, get, set, shown_desc,

// fills in the passed array with all fields in this register, and returns
// the number of elements and a bitmask showing bits not covered by fields.
shared method _get_all_fields(field *fields) -> (int, uint64) /* n, unmapped */ {
shared method _get_get_fields(_get_field *fields) -> (int, uint64) /* n, unmapped */ {
local uint64 unmapped;
unmapped[this.bitsize-1:0] = -1;
unmapped[this.bitsize - 1 : 0 ] = -1;
local int n = 0;
// TODO: it is inefficient to re-generate the field list each call
foreach f in (this.fields) {
local uint64 lsbs = 0;

// counting sort
foreach f in (_get_fields) {
local int lsb = f.lsb;
// sort 'fields' by lsb
local int i;
for (i = n; i > 0; --i) {
local int next_lsb = fields[i - 1].lsb;
if (next_lsb > lsb) {
fields[i] = fields[i - 1];
} else {
break;
}
}
fields[i] = f;
lsbs[lsb] = 1;
unmapped[lsb + f.bitsize - 1 : lsb] = 0;
++n;
}
assert n <= 64;
return (n, unmapped);
}

// fills in the passed array with all fields in this register, and returns
// the number of elements and a bitmask showing bits not covered by fields.
shared method _get_get_fields(_get_field *fields) -> (int, uint64) /* n, unmapped */ {
local uint64 unmapped;
unmapped[this.bitsize-1:0] = -1;
local int n = 0;
// TODO: it is inefficient to re-generate the field list each call
foreach f in (this._get_fields) {
local int lsb = f.lsb;
// sort 'fields' by lsb
local int i;
for (i = n; i > 0; --i) {
local int next_lsb = fields[i - 1].lsb;
if (next_lsb > lsb) {
fields[i] = fields[i - 1];
} else {
break;
}
}
fields[i] = f;
unmapped[lsb + f.bitsize - 1 : lsb] = 0;
++n;
foreach f in (_get_fields) {
fields[bit_count64(lsbs[f.lsb : 0]) - 1] = f;
}
assert n <= 64;
return (n, unmapped);
}

// fills in the passed array with all fields in this register, and returns
// the number of elements and a bitmask showing bits not covered by fields.
shared method _get_set_fields(_set_field *fields) -> (int, uint64) /* n, unmapped */ {
local uint64 unmapped;
unmapped[this.bitsize-1:0] = -1;
unmapped[this.bitsize - 1 : 0 ] = -1;
local int n = 0;
// TODO: it is inefficient to re-generate the field list each call
foreach f in (this._set_fields) {
local uint64 lsbs = 0;

// counting sort
foreach f in (_set_fields) {
local int lsb = f.lsb;
// sort 'fields' by lsb
local int i;
for (i = n; i > 0; --i) {
local int next_lsb = fields[i - 1].lsb;
if (next_lsb > lsb) {
fields[i] = fields[i - 1];
} else {
break;
}
}
fields[i] = f;
lsbs[lsb] = 1;
unmapped[lsb + f.bitsize - 1 : lsb] = 0;
++n;
}
assert n <= 64;

foreach f in (_set_fields) {
fields[bit_count64(lsbs[f.lsb : 0]) - 1] = f;
}
return (n, unmapped);
}

// fills in the passed array with all fields in this register, and returns
// the number of elements and a bitmask showing bits not covered by fields.
shared method _get_write_fields(_write_field *fields) -> (int, uint64) /* n, unmapped */ {
local uint64 unmapped;
unmapped[this.bitsize-1:0] = -1;
unmapped[this.bitsize - 1 : 0 ] = -1;
local int n = 0;
// TODO: it is inefficient to re-generate the field list each call
foreach f in (this._write_fields) {
local uint64 lsbs = 0;

// counting sort
foreach f in (_write_fields) {
local int lsb = f.lsb;
// sort 'fields' by lsb
local int i;
for (i = n; i > 0; --i) {
local int next_lsb = fields[i - 1].lsb;
if (next_lsb > lsb) {
fields[i] = fields[i - 1];
} else {
break;
}
}
fields[i] = f;
lsbs[lsb] = 1;
unmapped[lsb + f.bitsize - 1 : lsb] = 0;
++n;
}
assert n <= 64;

foreach f in (_write_fields) {
fields[bit_count64(lsbs[f.lsb : 0]) - 1] = f;
}
return (n, unmapped);
}

// fills in the passed array with all fields in this register, and returns
// the number of elements and a bitmask showing bits not covered by fields.
shared method _get_read_fields(_read_field *fields) -> (int, uint64) /* n, unmapped */ {
local uint64 unmapped;
unmapped[this.bitsize-1:0] = -1;
unmapped[this.bitsize - 1 : 0 ] = -1;
local int n = 0;
// TODO: it is inefficient to re-generate the field list each call
foreach f in (this._read_fields) {
local uint64 lsbs = 0;

// counting sort
foreach f in (_read_fields) {
local int lsb = f.lsb;
// sort 'fields' by lsb
local int i;
for (i = n; i > 0; --i) {
local int next_lsb = fields[i - 1].lsb;
if (next_lsb > lsb) {
fields[i] = fields[i - 1];
} else {
break;
}
}
fields[i] = f;
lsbs[lsb] = 1;
unmapped[lsb + f.bitsize - 1 : lsb] = 0;
++n;
}
assert n <= 64;

foreach f in (_read_fields) {
fields[bit_count64(lsbs[f.lsb : 0]) - 1] = f;
}
return (n, unmapped);
}

Expand Down