Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / devices / mem_bus / libdumbtod / dumbtod.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: dumbtod.c
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27#pragma ident "@(#)dumbtod.c 1.13 07/02/15 SMI"
28/*
29 * This is a very generic TOD device.
30 * It provides a single read-only 64-bit register that
31 * contains the time in standard Unix form: number of seconds
32 * since Jan 1, 1970 UST.
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <sys/types.h>
39#include <time.h>
40#include <strings.h>
41
42#include "basics.h"
43#include "allocate.h"
44#include "lexer.h"
45#include "simcore.h"
46#include "config.h"
47#include "dumpinfo.h"
48#include "fatal.h"
49#include "device.h"
50
51#define DBGX(s) do { } while (0)
52
53
54/*
55 * Registers
56 * addr RW SZ Function
57 * ----- -- ------ --------------
58 * 0x00 R 64-bit time_t
59 */
60
61
62static void dtod_parse(config_dev_t *);
63static void dtod_init(config_dev_t *);
64static void dtod_dump(config_dev_t *);
65static bool_t dtod_cpu_access(simcpu_t *sp, config_addr_t * cap,
66 tpaddr_t offset, maccess_t op, uint64_t * regp);
67
68dev_type_t dev_type_dumbtod = {
69 "dumbtod",
70 dtod_parse,
71 dtod_init,
72 dtod_dump,
73 generic_device_non_cacheable,
74 dtod_cpu_access,
75 DEV_MAGIC
76};
77
78typedef struct {
79 time_t start_time;
80 uint64_t sysclkfreq;
81 uint64_t todfreq;
82} dtod_state_t;
83
84
85/*
86 * Complete the creation and parsing of this specific device
87 */
88static void
89dtod_parse(config_dev_t *config_devp)
90{
91 dtod_state_t * dtp;
92 lexer_tok_t tok;
93
94 if (config_devp->addrp->range != 8)
95 fatal("dumbtod: dumbtod requires address space size of 0x8");
96
97DBG( printf("dumbtod_parse: parsing device %d\n", config_devp->device_id); );
98
99 dtp = (void*)Xcalloc(1, dtod_state_t);
100 dtp->todfreq = 1; /* defaults to 1 */
101
102 config_devp->devp = dtp;
103
104 tok = lex_get_token();
105 switch(tok) {
106 case T_S_Colon:
107 return;
108 case T_L_Brace:
109 break;
110 default:
111 lex_fatal("unexpected token");
112 }
113
114 /*
115 * Parse the optional tod frequency
116 */
117 tok = lex_get_token();
118 if (strcmp(lex.strp,"frequency") == 0) {
119 dtp->todfreq = parse_number_assign();
120 if (dtp->todfreq == 0x0)
121 lex_fatal("dumbtod: dumbtod cannot have a tod freq of 0");
122 printf("dumbtod_parse: setting tod frequency of %lld\n", dtp->todfreq);
123 }
124
125 lex_get(T_R_Brace);
126}
127
128
129/*
130 * Initialise the device after parsing is complete
131 */
132static void
133dtod_init(config_dev_t *config_devp)
134{
135 dtod_state_t * dtp;
136
137 dtp = config_devp->devp;
138 dtp->start_time = time(NULL);
139 dtp->sysclkfreq = 0; /* find put from first CPU access */
140}
141
142
143/*
144 * Configuration dump
145 */
146void
147dtod_dump(config_dev_t *config_devp)
148{
149}
150
151
152static bool_t
153dtod_cpu_access(simcpu_t *sp, config_addr_t *cap, tpaddr_t offset, maccess_t op,
154 uint64_t *regp)
155{
156 dtod_state_t * dtp;
157
158 if ((op & MA_Op_Mask) != MA_Ld && (op & MA_Op_Mask) != MA_LdSigned) {
159 EXEC_WARNING(("dumbtod: Illegal access - only loads allowed "
160 "to TOD device"));
161 return (false);
162 }
163
164 if (offset != 0 || (op & MA_Size_Mask) != MA_Size64) {
165 EXEC_WARNING(("dumbtod: Illegal device load access (%d bytes) "
166 "- offset (0x%d) not 8-byte sized or aligned",
167 1<<(op & MA_Size_Mask), offset));
168 return (false);
169 }
170
171 dtp = cap->config_devp->devp;
172
173#if WALL_TIME /* { */
174 if (options.walltime) {
175 *regp = time(NULL) * dtp->todfreq;
176 return (true);
177 }
178#endif /* } */
179 if (dtp->sysclkfreq == 0) {
180 /* First time through - obtain clock frequency. */
181 dtp->sysclkfreq = sp->config_procp->domainp->sysclkfreq;
182 }
183
184 *regp = (dtp->start_time + (time_t)(sp->cycle / dtp->sysclkfreq)) * dtp->todfreq;
185
186 return (true);
187}