Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / cpu / src / N2_Tlb.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2_Tlb.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 <string.h>
23#include "N2_Tlb.h"
24#include "N2_Core.h"
25#include "N2_Strand.h"
26
27N2_Tlb::N2_Tlb( Type type, uint_t size )/*{{{*/
28 :
29 SS_Tlb(type,size),
30 used(0),
31 used_count(0),
32 trie(this)
33{
34 clone = n2_clone;
35
36 used = new bool[tlb_size];
37 for (uint_t i=0; i < tlb_size; i++)
38 used[i] = false;
39}
40/*}}}*/
41N2_Tlb::N2_Tlb( N2_Tlb& tlb )/*{{{*/
42 :
43 SS_Tlb(tlb),
44 used(0),
45 used_count(tlb.used_count),
46 trie(tlb.trie,this)
47{
48 used = new bool[tlb_size];
49 memcpy(used,tlb.used,tlb_size * sizeof(bool));
50}
51/*}}}*/
52N2_Tlb::~N2_Tlb()/*{{{*/
53{
54 delete used;
55}
56/*}}}*/
57
58SS_Tlb* N2_Tlb::n2_clone( SS_Tlb* _tlb )/*{{{*/
59{
60 return new N2_Tlb(*(N2_Tlb*)_tlb);
61}
62/*}}}*/
63
64void N2_Tlb::snapshot( SS_SnapShot& ss, const char* prefix, const char* inst )/*{{{*/
65{
66 char tte_tag[SS_SnapShot::LINE_SIZE];
67
68 for (int i=0; i < size(); i++)
69 {
70 sprintf(tte_tag,"%s.%s_tlb.%d",prefix,inst,i);
71 ptr_table[i]->snapshot(ss,tte_tag);
72 }
73
74 // Clear the used field to make run after snapshot
75 // and run after restore behave the same.
76
77 clear_used();
78
79 if (ss.do_load())
80 {
81 // Populate the trie TLB after loading. To make sure that
82 // we make an exact restore of the original trie we insert
83 // the pages size by smaller first and biggest last:
84 // the page size (psz) 0 (8K) first, then page size 1 (64K),
85 // 3, and 5. Page size 2,4,6,7 are not used by N2.
86
87 for (int psz = 0; psz <=5; psz++)
88 {
89 if ((psz == 2) or (psz == 4))
90 continue;
91 for (int i=0; i < size(); i++)
92 if (ptr_table[i]->valid() && (ptr_table[i]->page_size() == psz))
93 trie.insert(0,ptr_table[i],0);
94 }
95 }
96}
97/*}}}*/
98
99void N2_Tlb::insert( SS_Tte* tte )/*{{{*/
100{
101 uint_t idx;
102 SS_Tte* old_tte;
103 SS_Tte* new_tte;
104
105 tlb_access_lock();
106
107 idx = get_free_tte();
108
109 old_tte = ptr_table[idx];
110 assert(old_tte->index == idx);
111
112 new_tte = alloc_tte(idx);
113 *new_tte = *tte;
114 new_tte->index = idx;
115 new_tte->adapt();
116
117 trie.insert(0,tte,old_tte);
118
119 set_used(idx);
120 ptr_table[idx] = new_tte;
121 flush_tte(0,old_tte);
122
123 tlb_access_unlock();
124}
125/*}}}*/
126
127SS_Tte* N2_Tlb::insert_tsb_tte( SS_Strand* strand, uint16_t pid, uint64_t tag, uint64_t data, SS_Vaddr va, int idx, int r )/*{{{*/
128{
129 SS_Tte* old_tte;
130 SS_Tte* new_tte;
131
132 tlb_access_lock();
133
134 if (idx < 0)
135 idx = get_free_tte();
136 else
137 idx = idx & (size() - 1);
138
139 old_tte = ptr_table[idx];
140 assert(old_tte->index == idx);
141
142 new_tte = alloc_tte(idx);
143 new_tte->insert_tsb_tte(pid,tag,data,va);
144 new_tte->real_bit(r);
145
146 N2_Strand* n2_strand = (N2_Strand *)strand;
147
148 if (n2_strand->sim_state.ras_enabled())
149 {
150 N2_Core& n2_core = n2_strand->core;
151
152 if (n2_core.error_inject.ene())
153 {
154 int tp_error = 0;
155 int dp_error = 0;
156
157 if (n2_core.error_inject.imtu() | n2_core.error_inject.dmtu())
158 tp_error = 1;
159
160 if (n2_core.error_inject.imdu() | n2_core.error_inject.dmdu())
161 dp_error = 1;
162
163 new_tte->tag_parity_error(tp_error);
164 new_tte->data_parity_error(dp_error);
165 }
166 }
167
168 // Insert the TTE into the trie so that the non mutexed
169 // lookup can find it. Note lookup does not use mutexes which
170 // means that insert and demap have to be coded carefully.
171 // The old TTE can be flushed after the new TTE is available.
172
173 trie.insert(strand,new_tte,old_tte);
174
175 ptr_table[idx] = new_tte;
176 set_used(idx);
177 flush_tte(strand,old_tte);
178
179 // Trace insertion of tte into this tlb
180 if (strand->trc_hook)
181 strand->trc_hook->tlb_update(true,this,new_tte->index,new_tte);
182
183 tlb_access_unlock();
184
185 return new_tte;
186}
187/*}}}*/
188
189void N2_Tlb::demap_virt( SS_Strand* strand, uint_t pid, uint_t context, SS_Vaddr va )/*{{{*/
190{
191 tlb_access_lock();
192 trie.demap_virt(strand,pid,context,va);
193 tlb_access_unlock();
194}
195/*}}}*/
196void N2_Tlb::demap_virt( SS_Strand* strand, uint_t pid, uint_t context )/*{{{*/
197{
198 tlb_access_lock();
199 trie.demap_virt(strand,pid,context);
200 tlb_access_unlock();
201}
202/*}}}*/
203void N2_Tlb::demap_virt( SS_Strand* strand, uint_t pid )/*{{{*/
204{
205 tlb_access_lock();
206 trie.demap_virt(strand,pid);
207 tlb_access_unlock();
208}
209/*}}}*/
210void N2_Tlb::demap_real( SS_Strand* strand, uint_t pid, SS_Vaddr va )/*{{{*/
211{
212 tlb_access_lock();
213 trie.demap_real(strand,pid,va);
214 tlb_access_unlock();
215}
216/*}}}*/
217void N2_Tlb::demap_real( SS_Strand* strand, uint_t pid )/*{{{*/
218{
219 tlb_access_lock();
220 trie.demap_real(strand,pid);
221 tlb_access_unlock();
222}
223/*}}}*/
224void N2_Tlb::demap_all( SS_Strand* strand, uint_t pid )/*{{{*/
225{
226 tlb_access_lock();
227 trie.demap_all(strand,pid);
228 tlb_access_unlock();
229}
230/*}}}*/