From 3feb5e2189bba285ed2ad47a6a7514b1f950b440 Mon Sep 17 00:00:00 2001
From: fche
Date: Tue, 12 Mar 2002 18:03:18 +0000
Subject: [PATCH] * mapper banking support
2002-03-11 Frank Ch. Eigler
* compMapper.cxx (overlaps_p, selected_p, bank_changed): New/modified
helper functions for banking.
(bank_pin_handler, connect_accessor, disconnect_accessor): Ditto.
(locate): Ditto.
(make_name_mapping): Ditto; reorganize, tighten. Change syntax of
word-multiplier construct.
(generic_mapper): Add new fields for bank tracking.
* hw-mapper-basic.xml: Document banking system and syntax.
* hw-mapper-basic.txt: Regenerated.
---
sid/component/mapper/ChangeLog | 12 +
sid/component/mapper/compMapper.cxx | 241 +++++++++++++++++----
sid/component/mapper/hw-mapper-basic.txt | 42 +++-
sid/component/mapper/hw-mapper-basic.xml | 47 ++--
sid/component/testsuite/ChangeLog | 5 +
.../testsuite/sidcomp.mapper/basicmapper.exp | 10 +-
6 files changed, 288 insertions(+), 69 deletions(-)
diff --git a/sid/component/mapper/ChangeLog b/sid/component/mapper/ChangeLog
index e46cebc5c2..7cde978dc6 100644
--- a/sid/component/mapper/ChangeLog
+++ b/sid/component/mapper/ChangeLog
@@ -1,3 +1,15 @@
+2002-03-11 Frank Ch. Eigler
+
+ * compMapper.cxx (overlaps_p, selected_p, bank_changed): New/modified
+ helper functions for banking.
+ (bank_pin_handler, connect_accessor, disconnect_accessor): Ditto.
+ (locate): Ditto.
+ (make_name_mapping): Ditto; reorganize, tighten. Change syntax of
+ word-multiplier construct.
+ (generic_mapper): Add new fields for bank tracking.
+ * hw-mapper-basic.xml: Document banking system and syntax.
+ * hw-mapper-basic.txt: Regenerated.
+
2001-10-10 Frank Ch. Eigler
* compMapper.cxx (generic_mapper_bus): New field low_multiplier.
diff --git a/sid/component/mapper/compMapper.cxx b/sid/component/mapper/compMapper.cxx
index a866f6d03d..339555ea62 100644
--- a/sid/component/mapper/compMapper.cxx
+++ b/sid/component/mapper/compMapper.cxx
@@ -1,6 +1,6 @@
// compMapper.cxx - a bus mapper component. -*- C++ -*-
-// Copyright (C) 1999-2001 Red Hat.
+// Copyright (C) 1999-2002 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
@@ -54,6 +54,7 @@ using sidutil::fixed_bus_map_component;
using sidutil::make_numeric_attribute;
using sidutil::parse_attribute;
using sidutil::tokenize;
+using sidutil::callback_pin;
using sidutil::attribute_coder_virtual_parameterized;
@@ -81,12 +82,23 @@ struct mapping_record
host_int_2 width_shift; // log2(width)
string spec; // user-given specification string
+
+ vector banks; // sorted list of bank #s in which this record is active
};
bool
overlaps_p (const mapping_record& a, const mapping_record& b)
{
+ // Reject disjoint banks
+ vector intersection (a.banks.size());
+ vector::iterator r =
+ set_intersection (a.banks.begin(), a.banks.end(),
+ b.banks.begin(), b.banks.end(),
+ intersection.begin());
+ if (r == intersection.begin()) // empty intersection?
+ return false;
+
// I always rederive this little formula from first principles.
host_int_4 max_first = max(a.low, b.low);
host_int_4 min_last = min(a.high, b.high);
@@ -94,22 +106,53 @@ overlaps_p (const mapping_record& a, const mapping_record& b)
}
-class mr_cmp: public std::binary_function
+bool
+selected_p (const mapping_record& a, host_int_4 bank)
+{
+#if 0
+ // This doesn't have to be fast, but since banks<> is kept sorted, might as well
+ // use binary search.
+
+ vector::const_iterator where =
+ lower_bound (a.banks.begin (), a.banks.end (), bank);
+
+ return (where != a.banks.end ());
+#endif
+
+ for (int i=0; i
{
public:
bool operator () (const mapping_record& a, const mapping_record& b) const
{
return (a.low < b.low);
}
+};
+
+class mr_ptr_cmp: public std::binary_function
+{
+public:
+ bool operator () (const mapping_record* a, const mapping_record* b) const
+ {
+ return (a->low < b->low);
+ }
- bool operator () (const mapping_record& a, host_int_4 addr) const
+ bool operator () (const mapping_record* a, host_int_4 addr) const
{
- return (a.high < addr);
+ return (a->high < addr);
}
- bool operator () (host_int_4 addr, const mapping_record& b) const
+ bool operator () (host_int_4 addr, const mapping_record* b) const
{
- return (addr < b.low);
+ return (addr < b->low);
}
};
@@ -124,8 +167,7 @@ class generic_mapper_bus: public bus
public:
generic_mapper_bus (generic_mapper* target, bool transparent_p): target (target)
{
- this->tlb1 = 0;
- this->tlb2 = 0;
+ this->tlb1 = this->tlb2 = 0;
this->low_multiplier = (transparent_p ? 0 : 1);
}
@@ -246,6 +288,9 @@ private:
mutable struct mapping_record* tlb1;
mutable struct mapping_record* tlb2;
unsigned low_multiplier;
+
+public:
+ void clear_tlb () { tlb1 = tlb2 = 0; }
};
generic_mapper_bus::~generic_mapper_bus () throw () {
@@ -276,9 +321,16 @@ public:
protected:
friend class generic_mapper_bus;
- vector accessors;
+ vector accessors; // All records
generic_mapper_bus my_bus;
+ // banking
+ vector selected_accessors; // All records in current bank
+ host_int_4 bank;
+ callback_pin bank_pin;
+ void bank_pin_handler (host_int_4);
+ void bank_changed ();
+
// stats
host_int_4 access_count;
host_int_4 cache_hit_count;
@@ -296,14 +348,20 @@ private:
generic_mapper::generic_mapper (bool transparent_p)
:my_bus (this, transparent_p),
+ bank (0),
+ bank_pin (this, & generic_mapper::bank_pin_handler),
latency (0)
{
add_bus ("access-port", &this->my_bus);
add_attribute_virtual ("state-snapshot", this,
& generic_mapper::save_state,
& generic_mapper::restore_state);
-
- add_attribute ("latency", &latency, "setting");
+
+ add_attribute ("latency", & this->latency, "setting");
+ add_attribute_notify ("bank", & this->bank,
+ this, & generic_mapper::bank_changed,
+ "register");
+ add_pin ("bank", & this->bank_pin);
this->access_count = 0;
add_attribute ("access-count", & this->access_count, "register");
@@ -312,6 +370,41 @@ generic_mapper::generic_mapper (bool transparent_p)
}
+
+void
+generic_mapper::bank_pin_handler (host_int_4 new_bank)
+{
+ this->bank = new_bank;
+ this->bank_changed ();
+}
+
+
+// Regenerate the selected-accessors sorted vector after the bank number
+// or overall accessor list have changed.
+void
+generic_mapper::bank_changed ()
+{
+ this->selected_accessors.clear ();
+
+ for (vector::iterator it = this->accessors.begin();
+ it != this->accessors.end();
+ it++)
+ {
+ if (selected_p (*it, this->bank))
+ {
+ // cout << "mapper bank " << this->bank << " sel: " << it->spec << endl;
+ this->selected_accessors.push_back (it);
+ }
+ }
+
+ sort (this->selected_accessors.begin(),
+ this->selected_accessors.end(),
+ mr_ptr_cmp ());
+
+ this->my_bus.clear_tlb ();
+}
+
+
vector
generic_mapper::accessor_names () throw()
{
@@ -347,7 +440,9 @@ generic_mapper::connect_accessor (const string& name, bus* bus) throw()
}
this->accessors.push_back (*r);
- sort(this->accessors.begin(),this->accessors.end(),mr_cmp());
+ // sort for aesthetic reasons
+ sort (this->accessors.begin(), this->accessors.end(), mr_value_cmp ());
+ this->bank_changed (); // recalculate selected_accessors
add_attribute_virtual_parameterized (name + "-hits",
name,
@@ -373,7 +468,9 @@ generic_mapper::disconnect_accessor (const string& name, bus* bus) throw()
{
remove_attribute (name + "-hits");
this->accessors.erase (it);
- sort(this->accessors.begin(),this->accessors.end(),mr_cmp());
+ // sort for aesthetic reasons
+ sort (this->accessors.begin(), this->accessors.end(), mr_value_cmp ());
+ this->bank_changed (); // recalculate selected_accessors
return component::ok;
}
}
@@ -488,10 +585,21 @@ generic_mapper_bus::read_any (host_int_4 address, Data& data) throw ()
// Return 0 on parse or validity-checking error.
//
// Accept the following forms:
-// [LOW-HIGH] (4 tokens)
-// [LOW-HIGH,STRIDE,WIDTH] (6 tokens)
-// [BYTES_PER_WORD,LOW-HIGH] (5 tokens)
-// [BYTES_PER_WORD,LOW-HIGH,STRIDE,WIDTH] (7 tokens)
+//
+// GARBAGE1[SPEC]GARBAGE2
+//
+// where SPEC ::=
+// LOW-HIGH (2 tokens)
+// LOW-HIGH,STRIDE,WIDTH (3 tokens)
+// BYTES_PER_WORD*LOW-HIGH (4 tokens)
+// BYTES_PER_WORD*LOW-HIGH,STRIDE,WIDTH (5 tokens)
+//
+// and GARBAGE2 ::=
+// {BANKS}GARBAGE3
+// or GARBAGE3
+//
+// where BANKS ::= specifies mapping banks
+// BANK1,BANK2,BANK3,... (0- tokens)
//
// Each number may be specified in any format that parse_attribute()
// understands.
@@ -502,36 +610,93 @@ generic_mapper::make_name_mapping (const string& str, bus* acc) const
// Fill in this struct in stack; may return copy if all goes well
mapping_record record;
- vector fields = tokenize (str, "[-,]");
+ vector fields_outer = tokenize (str, "[]");
+ if (fields_outer.size() != 3)
+ {
+ cerr << "mapper error: parse error (missing [SPEC]) in " << str << endl;
+ return 0;
+ }
+
+ string garbage1 = fields_outer[0];
+ string spec = fields_outer[1];
+ string garbage2 = fields_outer[2];
- // Must have between 4 and 7 tokens (including empties
- // before/after "[" and "]")
- if (fields.size() < 4 || fields.size() > 7)
+ // Process bank numbers spec
+ vector bankspec = tokenize (garbage2, "{}");
+
+ // cout << "suffix=" << garbage2 << endl;
+ // for (int j=0; j banks = tokenize (bankspec[1], ",");
+ for (unsigned i=0; i fields = tokenize (spec, "*-,");
+
+ // Must have between 2 and 5 tokens (including empties
+ // before/after "[" and "]"
+ if (fields.size() < 2 || fields.size() > 5)
+ {
+ cerr << "mapper error: parse error (bad number of [SPEC] fields) in "
+ << str << endl;
return 0;
}
// strip the word width off the front of the descriptor array
record.bytes_per_word = 1;
- if (fields.size() == 5 || fields.size() == 7)
+ if (fields.size() == 3 || fields.size() == 5)
{
- component::status stat = parse_attribute(fields [fields.size () - 2], record.bytes_per_word);
+ component::status stat = parse_attribute(fields [0], record.bytes_per_word);
if (stat != component::ok)
{
cerr << "mapper error: parse error (bytes_per_word) in " << str << endl;
return 0;
}
- fields.pop_back ();
+ fields.erase (fields.begin ());
}
+
+ assert (fields.size() == 2 || fields.size() == 4);
- record.use_strideoffset_p = (fields.size() == 6);
+ record.use_strideoffset_p = (fields.size() == 4);
record.spec = str;
record.hit_count = 0;
// parse two or four fields
- component::status s1 = parse_attribute(fields[1], record.low);
- component::status s2 = parse_attribute(fields[2], record.high);
+ component::status s1 = parse_attribute(fields[0], record.low);
+ component::status s2 = parse_attribute(fields[1], record.high);
if (s1 != component::ok || s2 != component::ok)
{
cerr << "mapper error: parse error (low-high) in " << str << endl;
@@ -539,8 +704,8 @@ generic_mapper::make_name_mapping (const string& str, bus* acc) const
}
if (record.use_strideoffset_p)
{
- component::status s3 = parse_attribute(fields[3], record.stride);
- component::status s4 = parse_attribute(fields[4], record.width);
+ component::status s3 = parse_attribute(fields[2], record.stride);
+ component::status s4 = parse_attribute(fields[3], record.width);
if (s3 != component::ok || s4 != component::ok)
{
cerr << "mapper error: parse error (stride,width) in " << str << endl;
@@ -660,17 +825,15 @@ generic_mapper_bus::locate (host_int_4 address) const
}
// binary search in one statement!
- vector::iterator where =
- lower_bound (this->target->accessors.begin (),
- this->target->accessors.end (),
- address,
- mr_cmp ());
-
- // XXX: other optimizations
+ vector::iterator where =
+ lower_bound (this->target->selected_accessors.begin (),
+ this->target->selected_accessors.end (),
+ address,
+ mr_ptr_cmp ());
- while (where != this->target->accessors.end ())
+ while (where != this->target->selected_accessors.end ())
{
- mapping_record* found = & * where;
+ mapping_record* found = *where;
// cout << " [found: " << found.first << "-" << found.last << "]" << endl;
// Incoming address is smaller than the first map entry?
diff --git a/sid/component/mapper/hw-mapper-basic.txt b/sid/component/mapper/hw-mapper-basic.txt
index dcbd22c798..e58c8ba064 100644
--- a/sid/component/mapper/hw-mapper-basic.txt
+++ b/sid/component/mapper/hw-mapper-basic.txt
@@ -14,14 +14,15 @@ Functionality:
This component distributes bus accesses to one of a number of configured
bus accessors, depending on the address of the incoming memory access.
- A mapper defines an address space. The address space is decomposed into
- non-overlapping regions by configuring a dynamic collection of accessors.
- Each accessor is connected to a single slave bus. To configure the address
- mapping, you must name each accessor according to one of these forms:
+ A mapper defines a group of address spaces. Each group is known as a bank.
+ Each address space is decomposed into non-overlapping regions by
+ configuring a dynamic collection of accessors. Each accessor is connected
+ to a single slave bus. To configure the address mapping, you must name
+ each accessor according to one of these forms:
* [-]
- * [-,]
+ * [*-]
* [-,,]
- * [-,,,]
+ * [*-,,]
where:
* is the starting address for the mapped region.
* is the ending address for the mapped region.
@@ -31,9 +32,15 @@ Functionality:
multiplier you can use to permit specifying , ,
and in terms of multi-byte words.
- In addition, any text may appear outside the "[" and "]" brackets, as long
- as that text does not include any of the separator characters "[" "]" "-"
- ",".
+ To the right of the "]" closing bracket, an optional specification block
+ may list the numbers of mapping banks for this record. This block is
+ formatted as a comma-separated list of numbers, given between "{" and "}"
+ brackets. The default is to reside in bank 0 only.
+
+ In addition, any text may appear to the left of the "[" and "]" brackets,
+ as long as that text does not include any of the characters "[" "]".
+ Likewise, text may appear to the right, but it must exclude the "[", "]",
+ "{", and "}" bracket characters.
Each number may be specified in decimal, hexadecimal, octal, and binary
forms, with the appropriate prefix (none, "0x", "0", "0b", respectively).
@@ -70,13 +77,24 @@ Functionality:
| | entry, or inconsistent ranges |
| | or stride/width values. |
|----------------+--------------------------------|
+ | banking | When the bank attribute is set |
+ | | with a numeric value, or the |
+ | | bank pin is driven with a |
+ | | number, the mapping group or |
+ | | bank number is instantly |
+ | | changed. Subsequent mapping |
+ | | activities will see only those |
+ | | mapping entries that include |
+ | | the new bank number. |
+ |----------------+--------------------------------|
| mapping | When an incoming access on the |
| | access-port bus is received, |
| | its base address is compared |
| | to all the registered outgoing |
- | | accessors. If one is found |
- | | that contains the address, the |
- | | current address is transformed |
+ | | accessors in the current bank. |
+ | | If one is found that contains |
+ | | the address, the current |
+ | | address is transformed |
| | according to the following |
| | rules: |
| | * The accessor's |
diff --git a/sid/component/mapper/hw-mapper-basic.xml b/sid/component/mapper/hw-mapper-basic.xml
index ae94c9bd28..bbc825592a 100644
--- a/sid/component/mapper/hw-mapper-basic.xml
+++ b/sid/component/mapper/hw-mapper-basic.xml
@@ -33,18 +33,20 @@
This component distributes bus accesses to one of a number of
configured bus accessors, depending on the address of the
incoming memory access.
+
- A mapper defines an address space. The address space is
- decomposed into non-overlapping regions by configuring a dynamic
- collection of accessors. Each accessor is connected to a single
- slave bus. To configure the address mapping, you must name each
- accessor according to one of these forms:
+ A mapper defines a group of address spaces. Each group is
+ known as a bank. Each address space is decomposed
+ into non-overlapping regions by configuring a dynamic
+ collection of accessors. Each accessor is connected to a
+ single slave bus. To configure the address mapping, you
+ must name each accessor according to one of these forms:
- [<low>-<high>]
- - [<low>-<high>,<wordsize>]
+ - [<wordsize>*<low>-<high>]
- [<low>-<high>,<stride>,<width>]
- - [<low>-<high>,<stride>,<width>,<wordsize>]
+ - [<wordsize>*<low>-<high>,<stride>,<width>]
where:
@@ -65,9 +67,17 @@
- In addition, any text may appear outside the "[" and "]" brackets,
- as long as that text does not include any of the separator
- characters "[" "]" "-" ",".
+ To the right of the "]" closing bracket, an optional specification block
+ may list the numbers of mapping banks for this record. This block is
+ formatted as a comma-separated list of numbers, given between "{" and "}"
+ brackets. The default is to reside in bank 0 only.
+
+
+ In addition, any text may appear to the left of the "[" and
+ "]" brackets, as long as that text does not include any of
+ the characters "[" "]". Likewise, text may appear to the
+ right, but it must exclude the "[", "]", "{", and "}"
+ bracket characters.
Each number may be specified in decimal, hexadecimal, octal, and
@@ -104,14 +114,25 @@
an existing entry, or inconsistent ranges or stride/width
values.
+
+
+
+ When the bank attribute is set with a
+ numeric value, or the bank pin is driven with a
+ number, the mapping group or bank number is instantly
+ changed. Subsequent mapping activities will see only those
+ mapping entries that include the new bank number.
+
+
+
When an incoming access on the access-port bus is
received, its base address is compared to all the registered
- outgoing accessors. If one is found that contains the
- address, the current address is transformed according to the
- following rules:
+ outgoing accessors in the current bank. If one is found
+ that contains the address, the current address is
+ transformed according to the following rules:
-
diff --git a/sid/component/testsuite/ChangeLog b/sid/component/testsuite/ChangeLog
index 0193d0daa4..e40a8a10ef 100644
--- a/sid/component/testsuite/ChangeLog
+++ b/sid/component/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2002-03-11 Frank Ch. Eigler
+
+ * sidcomp.mapper/basicmapper.exp: Update for new word-multiplier
+ syntax.
+
2002-01-22 Ben Elliston
* sidcomp.ide/idebase.exp: Delete "D:\\drive0" on completion.
diff --git a/sid/component/testsuite/sidcomp.mapper/basicmapper.exp b/sid/component/testsuite/sidcomp.mapper/basicmapper.exp
index 1804264d8c..55703f37c1 100644
--- a/sid/component/testsuite/sidcomp.mapper/basicmapper.exp
+++ b/sid/component/testsuite/sidcomp.mapper/basicmapper.exp
@@ -1,7 +1,7 @@
# -*- Tcl -*-
# basicmapper.exp
#
-# Copyright (C) 1999 Red Hat
+# Copyright (C) 1999, 2002 Red Hat
#
# Description:
# A testsuite for the generic mapper component (hw-mapper-basic).
@@ -77,20 +77,20 @@ set result [sid_cmd "sid::component::connect_accessor $victim [list $accname] $b
if {$result != "ok"} { fail "$test -- got $result" } else { pass $test }
set test "connect test bus #3 to the mapper"
-set accname {[0x300-0x600,8]}
+set accname {[8*0x300-0x600]}
set result [sid_cmd "sid::component::connect_accessor $victim [list $accname] $buses_array(3)"]
if {$result != "ok"} { fail "$test -- got $result" } else { pass $test }
set test "connect test bus #4 to the mapper"
-set accname {[0xff00-0xff01,4,1,4]}
+set accname {[1*0xff00-0xff01,4,1]}
set result [sid_cmd "sid::component::connect_accessor $victim [list $accname] $buses_array(4)"]
if {$result != "ok"} { fail "$test -- got $result" } else { pass $test }
-set test "three accessors are now registered"
+set test "four accessors are now registered"
set okay 1
set accessors [sid_cmd "sid::component::accessor_names $victim"]
-set expected {[0x100,0x200,1,1] [0x300-0x600,4,1] [0x300-0x600,8] [0xff00-0xff01,4,1,4]}
+set expected {[0x100,0x200,1,1] [0x300-0x600,4,1] [8*0x300-0x600] [1*0xff00-0xff01,4,1]}
if {[llength $accessors] != 4} {
fail $test
--
2.11.0