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