Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_AsiSpace.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: SS_AsiSpace.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21
22#include "SS_AsiSpace.h"
23#include "SS_Strand.h"
24#include "SS_AsiCtrReg.h"
25#include <stdio.h>
26#include <stdlib.h>
27#include <new>
28
29SS_AsiSpace::SS_AsiSpace()/*{{{*/
30 :
31 mask(~SS_Vaddr(0)),
32 fail(0,mask,0,0,no_rd,no_wr,no_rd,no_wr),
33 table(0),
34 table_copy(false),
35 block(0),
36 free_range_index(ALLOC),
37 alloc(0),
38 size(0),
39 asi(0)
40{}
41/*}}}*/
42SS_AsiSpace::~SS_AsiSpace()/*{{{*/
43{
44 if (table) free(table);
45 while (block)
46 {
47 Block* p = block;
48 block = p->next;
49 delete p;
50 }
51}
52/*}}}*/
53SS_AsiSpace::Error SS_AsiSpace::no_rd( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* )/*{{{*/
54{
55 return SS_AsiSpace::NO_READ;
56}
57/*}}}*/
58SS_AsiSpace::Error SS_AsiSpace::no_wr( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t )/*{{{*/
59{
60 return SS_AsiSpace::NO_WRITE;
61}
62/*}}}*/
63SS_AsiSpace::Error SS_AsiSpace::ld64( SS_Strand* s, SS_Vaddr addr, uint64_t* data )/*{{{*/
64{
65 addr &= mask;
66 Range* r = find(addr);
67 return (r->ld)(r->obj,r->reg,s,addr,data);
68}
69/*}}}*/
70SS_AsiSpace::Error SS_AsiSpace::st64( SS_Strand* s, SS_Vaddr addr, uint64_t data )/*{{{*/
71{
72 addr &= mask;
73 Range* r = find(addr);
74 return (r->st)(r->obj,r->reg,s,addr,data);
75}
76/*}}}*/
77SS_AsiSpace::Error SS_AsiSpace::rd64( SS_Strand* s, SS_Vaddr addr, uint64_t* data )/*{{{*/
78{
79 addr &= mask;
80 Range* r = find(addr);
81 return (r->rd)(r->obj,r->reg,s,addr,data);
82}
83/*}}}*/
84SS_AsiSpace::Error SS_AsiSpace::wr64( SS_Strand* s, SS_Vaddr addr, uint64_t data )/*{{{*/
85{
86 addr &= mask;
87 Range* r = find(addr);
88 return (r->wr)(r->obj,r->reg,s,addr,data);
89}
90/*}}}*/
91void SS_AsiSpace::merge( SS_AsiSpace& asi_space )/*{{{*/
92{
93 if (asi_space.size)
94 {
95 // If there is ranges defined in this space then we need to
96 // do some merging. If this is the first merge then we assume
97 // that the ranges associated with this ASI are defined at one
98 // level (SS_Node) only. If so then we can do a cheap copy.
99 // Else we need to do a quick copy and poper insert the rest
100
101 mask &= asi_space.mask;
102
103 if (size == 0) // do cheap copy first
104 {
105 alloc = asi_space.alloc;
106 size = asi_space.size;
107 table = asi_space.table;
108 table_copy = true;
109 }
110 else
111 {
112 if (table_copy) // real copy first, then insert proper
113 {
114 Range** old_table = table;
115 table = (Range**)malloc(sizeof(Range*) * alloc);
116 for (uint_t i=0; i < size; i++)
117 table[i] = old_table[i];
118 table_copy = false;
119 }
120 for (uint_t i=0; i < asi_space.size; i++)
121 add(asi_space.table[i]);
122 }
123 }
124}
125/*}}}*/
126void SS_AsiSpace::add( SS_Vaddr va, SS_Node* obj, SS_AsiCtrReg& reg )/*{{{*/
127{
128 add(va,va,obj,&reg,SS_AsiCtrReg::ld64,SS_AsiCtrReg::st64,SS_AsiCtrReg::rd64,SS_AsiCtrReg::wr64);
129}
130/*}}}*/
131void SS_AsiSpace::add( SS_Vaddr va, SS_Node* obj, SS_SharedAsiCtrReg& reg )/*{{{*/
132{
133 add(va,va,obj,&reg,SS_SharedAsiCtrReg::ld64,SS_SharedAsiCtrReg::st64,
134 SS_SharedAsiCtrReg::rd64,SS_SharedAsiCtrReg::wr64);
135}
136/*}}}*/
137void SS_AsiSpace::add( SS_Vaddr va, SS_Node* obj, void* reg, Read ld, Write st, Read rd, Write wr )/*{{{*/
138{
139 add(va,va,obj,reg,ld,st,rd,wr);
140}
141/*}}}*/
142void SS_AsiSpace::add( SS_Vaddr lo, SS_Vaddr hi, SS_Node* obj, void* reg, Read ld, Write st, Read rd, Write wr )/*{{{*/
143{
144 if (ld == 0) ld = no_rd;
145 if (st == 0) st = no_wr;
146 if (rd == 0) rd = no_rd;
147 if (wr == 0) wr = no_wr;
148
149 if (size == alloc)
150 {
151 alloc += ALLOC;
152 table = (Range**)realloc(table,sizeof(Range*) * alloc);
153 }
154
155 if (free_range_index == ALLOC)
156 {
157 // Allocate a new block of Range object. Avoid the C++ constructor
158 // call as each range will be initialised below anyways.
159
160 free_range_index = 0;
161 Block* new_block = (Block*)malloc(sizeof(Block));
162 new_block->next = block;
163 block = new_block;
164 }
165
166 Range* new_range = &block->page[free_range_index++];
167 new(new_range) Range(lo,hi,obj,reg,ld,st,rd,wr);
168
169 add(new_range);
170}
171/*}}}*/
172void SS_AsiSpace::add( Range* new_range )/*{{{*/
173{
174 if (size == alloc)
175 {
176 alloc += ALLOC;
177 table = (Range**)realloc(table,sizeof(Range*) * alloc);
178 }
179
180 SS_Vaddr hi = new_range->hi;
181 SS_Vaddr lo = new_range->lo;
182
183 // Check if we can just append the new range first.
184 // This will save a lot of time binary searching and
185 // moving part of the table around.
186
187 if ((size == 0) || (table[size - 1]->hi < new_range->lo))
188 {
189 table[size] = new_range;
190 }
191 else
192 {
193 uint_t l = 0;
194 uint_t h = size;
195 uint_t m = size >> 1;
196 Range* r = table[m];
197
198 while (l != m)
199 {
200 ((hi < r->lo) ? h : l) = m;
201 m = l + ((h - l) >> 1);
202 r = table[m];
203 }
204 if (hi < r->lo)
205 {
206 for (uint_t i=size; i > m; i--)
207 table[i] = table[i-1];
208 table[m] = new_range;
209 }
210 else if (r->hi < lo)
211 {
212 for (uint_t i=size; i > (m + 1); i--)
213 table[i] = table[i-1];
214 table[m+1] = new_range;
215 }
216 else
217 {
218 fprintf(stderr,"SS_AsiSpace: asi 0x%x add with lo=0x%llx and hi=0x%llx overlaps with lo=0x%llx and hi=0x%llx\n",asi(),lo,hi,r->lo,r->hi);
219 exit(-1);
220 }
221 }
222
223 ++size;
224}
225/*}}}*/